Delphi Indy HTTP服务器处理multipart请求时的编码问题求助
问题排查及修复方案
问题1:文本字段(如dir)末尾带多余字符
原因
你直接通过string(PAnsiChar(MS.Memory))读取流内容,PAnsiChar依赖#0作为终止符,但TMemoryStream存储的表单字段内容末尾没有自动追加#0,会读取到流后方的随机内存数据,导致dir字段值Upload后出现多余的W字符。
修复方法
按流实际长度读取内容,同时指定UTF-8编码解析文本字段:
// 替换原来的 Value := string(PAnsiChar(MS.Memory)); if MS.Size > 0 then Value := TEncoding.UTF8.GetString(MS.Memory, MS.Size) else Value := '';
问题2:文件名乱码
原因
Indy的TIdMessageDecoderMIME默认使用ISO-8859-1(Latin1)编码解析header中的filename字段,而浏览器传输的filename是UTF-8编码,相当于把UTF-8字节按单字节编码强制转成了字符串,才会出现ÄŤeská teÄŤka.png这类乱码。
修复方法
把Indy读取到的filename先转回原始字节,再用UTF-8重新解码:
// 替换原来的 Writeln(Decoder.Filename + ' ' + IntToStr(MS.Size)); var Latin1Enc: TEncoding; RawNameBytes: TBytes; CorrectFileName: string; begin Latin1Enc := TEncoding.GetEncoding(28591); // ISO-8859-1编码 try RawNameBytes := Latin1Enc.GetBytes(Decoder.Filename); CorrectFileName := TEncoding.UTF8.GetString(RawNameBytes); finally Latin1Enc.Free; end; Writeln(CorrectFileName + ' ' + IntToStr(MS.Size)); end;
完整修改后的ProcessAttachmentPart代码
procedure ProcessAttachmentPart(var Decoder: TIdMessageDecoder; var MsgEnd: Boolean); var MS: TMemoryStream; Name: string; Value: string; NewDecoder: TIdMessageDecoder; Latin1Enc: TEncoding; RawNameBytes: TBytes; CorrectFileName: string; begin MS := TMemoryStream.Create; try TIdMessageDecoderMIME(Decoder).Headers.Values['Content-Transfer-Encoding'] := '8bit'; TIdMessageDecoderMIME(Decoder).BodyEncoded := False; NewDecoder := Decoder.ReadBody(MS, MsgEnd); MS.Position := 0; if Decoder.Filename <> EmptyStr then begin try Latin1Enc := TEncoding.GetEncoding(28591); try RawNameBytes := Latin1Enc.GetBytes(Decoder.Filename); CorrectFileName := TEncoding.UTF8.GetString(RawNameBytes); finally Latin1Enc.Free; end; Writeln(CorrectFileName + ' ' + IntToStr(MS.Size)); except FreeAndNil(NewDecoder); Writeln('Error processing MIME'); end; end else begin Name := ExtractHeaderSubItem(Decoder.Headers.Text, 'name', QuoteHTTP); if Name <> EmptyStr then begin if MS.Size > 0 then Value := TEncoding.UTF8.GetString(MS.Memory, MS.Size) else Value := ''; try Writeln(Name + '=' + Value); except FreeAndNil(NewDecoder); Writeln('Error processing MIME'); end; end; end; Decoder.Free; Decoder := NewDecoder; finally MS.Free; end; end;
内容的提问来源于stack exchange,提问作者stepand76
相关产品推荐
相关产品推荐

