You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:54:04