使用Indy 10与Delphi 6处理POST请求Unicode参数的问题
在Delphi 6 + Indy 10中以UTF-8格式获取POST请求参数
因为Delphi 6是ANSI环境,Indy 10默认会用系统默认ANSI代码页解析POST参数,导致非当前代码页的UTF-8字符(比如ö)丢失编码信息。要绕开这个问题,你可以直接读取原始POST请求流的字节,手动按UTF-8解析参数,而不是使用ARequestInfo.Params。
解决方案步骤
- 直接读取
ARequestInfo.PostStream中的原始字节,这些字节是客户端发送的UTF-8编码数据 - 将原始字节转换为UTF-8格式的ANSI字符串(Delphi 6中
string是ANSI类型,但可以直接存储UTF-8字节序列) - 手动解析UTF-8字符串中的URL编码键值对,使用Indy自带的URL解码函数处理转义字符
代码实现
首先添加IdURI单元到uses列表,然后实现参数解析的辅助函数:
function ParseUTF8Params(const AUTF8Str: string): TStringList; var I: Integer; Pair, Key, Value: string; begin Result := TStringList.Create; Result.Delimiter := '&'; Result.DelimitedText := AUTF8Str; for I := 0 to Result.Count - 1 do begin Pair := TIdURI.Decode(Result[I]); // 解码URL转义的UTF-8字符 I := Pos('=', Pair); if I > 0 then begin Key := Copy(Pair, 1, I - 1); Value := Copy(Pair, I + 1, MaxInt); Result.Values[Key] := Value; end else Result.Values[Pair] := ''; end; end;
然后在请求处理函数中使用该函数:
procedure TTheServer._serverCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var UTF8PostData: string; UTF8Params: TStringList; begin // 仅处理POST表单请求 if (ARequestInfo.CommandType = hcPOST) and (Pos('application/x-www-form-urlencoded', ARequestInfo.ContentType) > 0) then begin if Assigned(ARequestInfo.PostStream) then begin // 读取原始UTF-8字节流 SetLength(UTF8PostData, ARequestInfo.PostStream.Size); ARequestInfo.PostStream.ReadBuffer(UTF8PostData[1], ARequestInfo.PostStream.Size); // 解析UTF-8参数 UTF8Params := ParseUTF8Params(UTF8PostData); try // 这里获取的参数值是UTF-8格式,可直接用于存储或后续UTF-8相关处理 // 示例:获取ParamName参数 ShowMessage(UTF8Params.Values['ParamName']); finally UTF8Params.Free; end; end; end else begin // 处理GET请求或其他类型请求的逻辑 // GET参数可通过ARequestInfo.UnparsedParams读取,同样用ParseUTF8Params解析 end; end;
关键注意事项
- 确保客户端发送POST请求时,表单数据确实以UTF-8编码,并且Content-Type最好指定
charset=UTF-8(如application/x-www-form-urlencoded; charset=UTF-8) - Delphi 6中
string存储UTF-8字节时,不要用系统默认的字符串转换函数(如AnsiToWideString)直接转换,需使用UTF-8专用转换函数(Indy的IdGlobal单元中有UTF8Decode可转成WideString) - 若需将UTF-8字符串显示在VCL控件中,需先转成WideString再赋值,避免乱码
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

