Delphi 7+Indy 10 HTTP服务器UTF-8编码响应发送问题
在Delphi 7 + Indy 10 HTTP服务器中正确发送UTF-8编码的特殊字符响应
核心原因
Indy 10 与 Indy 9 的字符串处理逻辑差异显著:在Delphi 7(ANSI环境)下,Indy 10 的ContentText属性会自动将赋值的ANSI字符串转换为CharSet指定的编码。如果直接把UTF-8字节以ANSI字符串形式赋值,会触发重复编码转换,导致特殊字符乱码(比如ő变成无重音的o)。
正确解决方案
方案1:直接使用ANSI字符串(最简单可靠)
如果你的原始字符串是Delphi 7默认的ANSI格式(包含ő、á等特殊字符),只需设置CharSet为utf-8,Indy 10会自动完成ANSI到UTF-8的转换,同时在响应头的Content-Type中带上charset=utf-8:
procedure TYourForm.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); begin // 设置响应字符集为UTF-8 AResponseInfo.CharSet := 'utf-8'; // 直接赋值ANSI格式的字符串(包含ő、á等特殊字符) AResponseInfo.ContentText := '示例内容:ő、á、é、ű'; end;
方案2:处理已有的UTF-8字节流
如果你的数据已经是UTF-8编码的字节(比如从文件读取、接口获取的UTF-8数据),不要使用ContentText,改用ContentStream直接发送原始字节,避免Indy的自动转换:
procedure TYourForm.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var UTF8MemStream: TMemoryStream; UTF8Data: array of Byte; begin // 示例:构造包含ő(UTF-8: $C5 $91)、á(UTF-8: $C3 $A1)的字节数组 SetLength(UTF8Data, 14); UTF8Data[0] := $53; UTF8Data[1] := $61; UTF8Data[2] := $6D; // "Sam" UTF8Data[3] := $70; UTF8Data[4] := $6C; UTF8Data[5] := $65; // "ple" UTF8Data[6] := $3A; UTF8Data[7] := $20; // ": " UTF8Data[8] := $C5; UTF8Data[9] := $91; // ő UTF8Data[10] := $2C; UTF8Data[11] := $20; // ", " UTF8Data[12] := $C3; UTF8Data[13] := $A1; // á UTF8MemStream := TMemoryStream.Create; try UTF8MemStream.WriteBuffer(UTF8Data[0], Length(UTF8Data)); UTF8MemStream.Position := 0; // 赋值流给响应,Indy会自动发送流中原始字节 AResponseInfo.ContentStream := UTF8MemStream; // 明确指定字符集和Content-Type AResponseInfo.CharSet := 'utf-8'; AResponseInfo.ContentType := 'text/plain; charset=utf-8'; // 注意:不要手动释放UTF8MemStream,Indy会在响应发送完成后自动释放 except UTF8MemStream.Free; raise; end; end;
关键注意事项
- 禁止将UTF-8字节以ANSI字符串形式赋值给
ContentText,这会触发Indy的二次编码转换,必然导致乱码。 - 若必须处理UTF-8格式的字符串(比如从其他UTF-8来源得到的字符串),可以先将其转换为ANSI字符串(使用
TIdTextEncoding.UTF8.GetString()),再用方案1处理,但更推荐直接用方案2的流方式。 - Indy 10在ANSI版本Delphi中没有
DefStringEncoding属性,因此无法跳过ContentText的自动转换,流方式是最直接的替代方案。
内容的提问来源于stack exchange,提问作者Fenistil
相关产品推荐
相关产品推荐

