Delphi XE8 idHttp Erromessage 文本编码错误

Delphi XE8 idHttp Erromessage text coding is wrong

我正在使用 Delphi XE8,我正在通过 idHttp 发送 PUT 消息。

  Http.Request.CustomHeaders.Clear;
  Http.Request.BasicAuthentication := false;
  http.Request.Method := 'PUT';
  Http.Request.Accept := '*/*';
  Http.Request.ContentType := 'application/json';
  http.Request.CustomHeaders.AddValue('apiKey','T_API23207_169');
  http.Request.CustomHeaders.AddValue('transactionId','20200924_015');
  http.Request.CustomHeaders.AddValue('usziID','1');
  Http.Request.AcceptEncoding := '*';
  http.Request.CharSet := 'utf-8';

  kuldes_header.Text := http.Request.CustomHeaders.Text;

  http.Intercept := IdLogEvent1;
  IdLogEvent1.Active := true;

  jsonToSend := TStringStream.create(json_adat.Text,system.sysUtils.TEncoding.UTF8);

  kuldes_body.Lines.LoadFromStream(jsonToSend);

  try
    try
        send_text := http.Put('http://10.109.132.24:8090/rest/usziIroda/1',jsonToSend);
        resp := http.ResponseText;
        code := http.ResponseCode;
        jsonToSend.Position := 0;
    except
        on E: EIdHTTPProtocolException do
          begin
          code := e.ErrorCode;
          error_message := e.ErrorMessage;
          end;
    end;

    hiba_kod.Lines.Add(IntToStr(code));
    valasz_uzenet.Text := send_text;
    hiba_uzenet.Text := error_message;   enter code here

返回的错误信息有奇怪的字符: "Megadott tranzakció azonosóval már történt API hávás"

但应该是这样的: "Megadott tranzakció azonosítóval már történt API hívás"

如何将返回的消息转换为普通字符串?

谢谢!

您显示的结果 - Megadott tranzakció azonosítóval már történt API hívás - 是 Megadott tranzakció azonosí­tóval már történt API hí­vás 的 UTF-8 编码形式在 Latin-1/ISO-8859-1 中被误解了。这很可能意味着响应没有在其 Content-Type header 中指定 UTF-8 字符集(因为您分配了 Intercept,您可以轻松地自己验证这一点),所以 Indy将退回到默认字符集。

在您可以访问 send_texterror_message 中的响应数据之前,原始 UTF-8 字节已被解码并丢失。但是,由于 ISO-8859-1 在字节值和 Unicode 代码点值之间基本上具有 1:1 关系,因此在这种特定情况下您可以尝试复制 ErrorMessageCharas-isRawByteString(65001)UTF8String,然后让 RTL 将其解码为 UTF-8 回到正确的 UTF-16 (Unicode)String,例如:

function DecodeISO88591AsUTF8(const S: string): string;
var
  utf8: UTF8String;
  I: Integer;
begin
  SetLength(utf8, Length(S));
  for I := Low(S) to High(S) do
    utf8[I] := AnsiChar(S[I]);
  Result := string(utf8);
end;

...

error_message := e.ErrorMessage;
//if not TextIsSame(http.Response.CharSet, 'utf-8') then
if TextIsSame(http.Response.CharSet, 'ISO-8859-1') then
  error_message := DecodeISO88591AsUTF8(error_message);

或者,您可以改为调用 TIdHTTP.Put() 的重载版本来填充响应 TStream 而不是返回已解码的 String,然后您可以解码原始原始字节你要。只要确保在 TIdHTTP.HTTPOptions 属性 中启用 hoNoProtocolErrorExceptionhoWantProtocolErrorContent 标志,以便任何错误响应都存储在 TStream 中,那么你就不会需要 try/except 来单独处理 EIdHTTPProtocolException

http.HTTPOptions := http.HTTPOptions + [hoNoProtocolErrorException, hoWantProtocolErrorContent];

...

RespStrm := TMemoryStream.Create;
try
  http.Put('http://10.109.132.24:8090/rest/usziIroda/1', jsonToSend, RespStrm);
  resp := http.ResponseText;
  code := http.ResponseCode;
  jsonToSend.Position := 0;
  RespStrm.Position := 0;

  if (code div 100) = 2 then
  begin
    send_text := decode RespStrm as needed...;
  end else
  begin
    error_message := decode RespStrm as needed...;
  end;
finally
  RespStrm.Free;
end;

...