【问题标题】:UTF-8 GET using Indy 10.5.8.0 and Delphi XE2使用 Indy 10.5.8.0 和 Delphi XE2 的 UTF-8 GET
【发布时间】:2012-10-09 21:35:46
【问题描述】:

我正在使用 Delphi XE2 编写我的第一个 Unicode 应用程序,我偶然发现了 GET 对 Unicode URL 的请求的问题。

简而言之,它是 MP3 标记应用程序中的一个例程,它获取曲目标题和艺术家,并在 Last.FM 中查询相应的专辑、曲目编号和流派。

我有以下代码:

function GetMP3Info(artist, track: string) : TMP3Data //<---(This is a record)
var
  TrackTitle,
  ArtistTitle : WideString;
  webquery    : WideString;

[....]

WebQuery := UTF8Encode('http://ws.audioscrobbler.com/2.0/?method=track.getcorrection&api_key=' + apikey + '&artist=' + artist + '&track=' + track);

//[processing the result in the web query, getting the correction for the artist and title]

// eg: for artist := Bucovina and track := Mestecanis, the corrected values are 
//ArtistTitle := Bucovina;
// TrackTitle := Mestecăniș;

//Now here is the tricky part:

webquery := UTF8Encode('http://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key=' + apikey + '&artist=' + unescape(ArtistTitle) + '&track=' + unescape(TrackTitle)); 
//the unescape function replaces spaces (' ') with '+' to comply with the last.fm requests

[some more processing]

end;

TMemo 中的网络查询看起来恰到好处:

http://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key=e5565002840xxxxxxxxxxxxxx23b98ad&artist=Bucovina&track=Mestecăniș

然而,当我尝试使用TIdHTTP(将ContentEncoding 属性设置为'UTF-8')向网络查询发送GET 请求时,我在Wireshark 中看到TIdHTTPGET'ing使用 ANSI 请求 URL 的数据:

/2.0/?method=track.getInfo&api_key=e5565002840xxxxxxxxxxxxxx23b98ad&artist=Bucovina&track=Mestec?ni?

以下是 GET 请求和响应的完整标头:

GET /2.0/?method=track.getInfo&api_key=e5565002840xxxxxxxxxxxxxx23b98ad&artist=Bucovina&track=Mestec?ni? HTTP/1.1
Content-Encoding: UTF-8
Host: ws.audioscrobbler.com
Accept: text/html, */*
Accept-Encoding: identity
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.23) Gecko/20110920 Firefox/3.6.23 SearchToolbar/1.22011-10-16 20:20:07

HTTP/1.0 400 Bad Request
Date: Tue, 09 Oct 2012 20:46:31 GMT
Server: Apache/2.2.22 (Unix)
X-Web-Node: www204
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Max-Age: 86400
Cache-Control: max-age=10
Expires: Tue, 09 Oct 2012 20:46:42 GMT
Content-Length: 114
Connection: close
Content-Type: text/xml; charset=utf-8;

<?xml version="1.0" encoding="utf-8"?>
<lfm status="failed">
<error code="6">
    Track not found
</error>
</lfm>

让我感到困惑的问题是,我是否在监督与设置TIdHTTP 组件的属性相关的任何事情?如何阻止我在应用程序中编写的格式正确的 URL 以错误的格式发送到服务器?

【问题讨论】:

  • @Tlama,你的建议奏效了。我欠你一些积分,但你之前的评论似乎已被删除。我怎样才能接受您(现已删除)的回答?
  • 是我删除了那条评论,我已经从它发了一个回复帖。

标签: delphi delphi-xe2 indy indy10 last.fm


【解决方案1】:

要从 track.getCorrection 函数中获取 XML 响应,您可以使用以下内容:

uses
  IdHTTP, IdURI;

function GetMusicDataXML(const AArtist, ATrack: string): string;
var
  URL: string;
  IdHTTP: TIdHTTP;
const
  APIKey = '1a3d8080e427f4dxxxxxxxxxxxxxxxxx';
begin
  Result := '';
  IdHTTP := TIdHTTP.Create;
  try
    URL := TIdURI.URLEncode('http://ws.audioscrobbler.com/2.0/?method=track.getcorrection&api_key=' + APIKey + '&artist=' + AArtist + '&track=' + ATrack);
    Result := IdHTTP.Get(URL);
  finally
    IdHTTP.Free;
  end;
end;

【讨论】:

  • 谢谢,成功了。我使用了错误的函数来对我的数据进行 UTF-8 编码。非常感谢您的回复。
【解决方案2】:
var
  ...
  webquery    : WideString; 
...
WebQuery := UTF8Encode('http://ws.audioscrobbler.com/2.0/?method=track.getcorrection&api_key=' + apikey + '&artist=' + artist + '&track=' + track); 

这并不像你认为的那样。在 XE2 中,UTF8Encode() 返回一个 UTF-8 编码的RawByteString,然后您将其分配给WideString。 RTL 会将 UTF-8 数据解码回 UTF-16 字符串。当您将该字符串传递给TIdHTTP.Get() 时,它会在格式化实际 HTTP 请求时将其转换为 ASCII,从而丢失所有非 ASCII 字符。

正如@TLama 所说,您必须使用TIdURI 对URL 进行编码,然后再将其传递给TIdHTTPTIdURI 会将 Unicode 字符编码为 UTF-8(默认情况下 - 如果需要,您可以指定编码),然后以TIdHTTP 不会丢失的 ASCII 兼容格式对结果数据进行编码。

【讨论】:

  • 我是这么想的,经过几个小时的反复试验,我决定请教 SE 专家。虽然我一开始以为我没有正确设置 IdHTTP 组件。
猜你喜欢
  • 1970-01-01
  • 2020-04-19
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 2014-09-22
相关资源
最近更新 更多