Delphi Indy Post 编码和 PHP

Delphi Indy Post Encoding and PHP

来自 php 脚本的字符串 return 已编码。

我对 delphi 2007 中的 http post 和 php 脚本的 Indy 10.6 有问题。 php 脚本包含: header ("Content-Type: application / json; charset = UTF-8"); Delphi 部分是这样的:

  data: = TStringList.Create;

  dati.Values ​​['id']: = '6';
  dati.Values ​​['name']: = 'àèìòù';

  lParams: = TIdMultiPartFormDataStream.Create;
  cont: = 0;
  try
    try
      url: = 'someurl';
      while cont <= data.Count-1 do
      begin
        lParams.AddFormField (data.Names [cont], data.Values ​​[data.Names [cont]]);
        Inc (cont);
      end;
      Response: = IdHTTP1.Post (url, lParams);
    except
      on E: Exception do
      Response: = E.ClassName + ':' + E.Message;
    end;
  finally
    lParams.Free;
    IdHTTP1.Disconnect;
  end;
  Result: = Response;

响应包含应保存在 mysql 数据库中的内容,其 varchar 字段声明为 utf8-general-i 然而,在现场和 php 回声中,他们 return: = E0 = E8 = EC = F2 = F9

我尝试使用 UTF8Encode 进行编码 (dati.Values [data.Names [cont]]),我尝试将 UTF-8 字符集传递给 AddFormField 但字符串 àèìòù 永远不会 returned.

我做错了什么?

您显示的内容看起来像 MIME 的 quoted-printable 编码,其中 non-ASCII/reserved 字节八位字节以 =HH 十六进制格式编码。 TIdMultiPartFormDataStream 默认情况下以 quoted-printable 格式对文本字段进行编码。 =E0=E8=EC=F2=F9 是字节序列 $E0 $E8 $EC $F2 $F9 的 QP-encoded 形式,它是用 Latin-1 (ISO-8859-1) 字符集编码的文本 'àèìòù'

PHP不支持multipart/form-data提交的Content-Transfer-Encodingheader(see this),所以不会自动给你解码QP编码.因此,您必须:

  • 在您的 PHP 脚本代码中手动解码 QP 编码。

  • 通过将 TIdFormDataField.ContentTransfer 属性 设置为 '8bit' 而不是默认的 'quoted-printable' 来禁用 TIdMultipartFormDataStream 应用 QP 编码(请注意,RFC 7578 不赞成在 multipart/form-data 通过 HTTP 提交中使用 Content-Transfer-Encoding header,但 TIdMultipartFormDataStream 尚未更新以说明 1).

    1:注意 - TIdFormDataField.ContentTransfer 属性 可以 设置为空字符串,这将禁用 Content-Transfer-Encoding header 从被发送,但它也会发送文本作为 7 位 US-ASCII,根据 RFC 2045 Section 6.1,所以如果您需要发送包含的文本,请不要使用此选项non-ASCII 个字符。

此外,请注意 Delphi 2007 不是 Delphi 的 Unicode 启用版本(即 String = AnsiString),这就是为什么您的文字是在 Latin-1 中发布。在 pre-Unicode 版本中,TIdMultiPartFormDataStream 传输 AnsiString 数据 as-is,因此您负责 pre-encoding 以所需字节编码发布的 AnsiString,比如UTF-8.

试试这个:

url := 'someurl';

try
  data := TStringList.Create;
  try
    data.Values ​​['id']: = '6';
    data.Values ​​['name'] := UTF8Encode('àèìòù'); // <-- omit UTF8Encode() in D2009+...

    lParams := TIdMultiPartFormDataStream.Create;
    try
      for cont := 0 to data.Count-1 do
      begin
        lParams.AddFormField(data.Names[cont], data.ValueFromIndex[cont], 'utf-8').ContentTransfer := '8bit';
      end;

      try
        Response := IdHTTP1.Post(url, lParams);
      finally
        IdHTTP1.Disconnect;
      end;
    finally
      lParams.Free;
    end;
  finally
    data.Free;
  end;
except
  on E: Exception do
    Response := E.ClassName + ':' + E.Message;
end;

Result := Response;