【问题标题】:TIdHTTPServer file uploadTIdHTTPServer 文件上传
【发布时间】:2011-09-05 16:35:58
【问题描述】:

我正在尝试将文件上传到 Indy(10.5.5 版)TIdHTTPServer。
我一直在寻找解决方案,但到目前为止没有运气,我发现旧版本的 Indy 与 Delphi 2010 附带的版本不兼容。

我希望实现简单地上传使用“multipart/form-data”的文件到服务器并解码它,就这么简单,任何帮助感激不尽。

【问题讨论】:

  • 对于 MIME 解码部分,Indy 在单元Protocols\IdCoderMIME 中包含一个TIdDecoderMIME
  • 是的,但不幸的是,它无法处理我需要的数据...谢谢您的评论
  • 10.5.5 不是很旧,但我会尝试当前的 Indy 10.5.8 版本
  • 是的,但不幸的是,我需要确保任何干净安装 Delphi 2010 的人都可以简单地构建项目,而无需更新 indy 或任何其他组件......要求。

标签: delphi delphi-2010 indy10


【解决方案1】:

TIdHTTPServer 目前不支持原生 multipart/form-data 提交。这是 Indy 11 的待办事项列表。与此同时,您必须按照 mjn 的建议,使用 TIdDecoderMIME 手动解析发布的 MIME 数据。之前在 Embarcadero 和 Indy 论坛上已经发布过这样的示例。

【讨论】:

  • 嗨 Remy,我已经设法找到了......可用的演示没有正确解析数据,它在文件中留下了结束边界......作为“服务器的 OnCreatePostStream" 事件我只是创建一个文件流,在 "OnCommandGet" 事件中我只是跳过边界并在 "最终文件流" 中复制正确的数据,它似乎正在工作,至少目前我需要...
  • 如果留下边界,则说明您没有正确处理数据。您具体看的是哪些演示?
  • forums2.atozed.com/viewtopic.php?f=7&t=23732 第二个帖子是你的我相信(gambit47?),mcptEOF 在 Indy 10.5.5 中不存在,但我仍然尝试上传,有时(上传大文件时,数百megs ZIP 或 RAR 文件)边界被删除,在其他情况下,如 PDF 的边界被留下,我相信它在读取流内容时与 CR、LF、CRLF 组合有关。目前,“OnCreatePostStream”我创建一个文件流,“OnCommandGet”我使用 ReadLnFromStream 绕过前 4 行(边界和文件信息)并读取直到...
  • 文件末尾减去(2 字节 + 边界长度“------MARKER--”)并且它可以工作,但是我想要一个更优雅的解决方案,如果可能的话.
  • 是的,我是那个论坛上的 gambit47。引入 mcptIgnoremcptEOF 以解决解析嵌套 MIME 部分的问题。 10.5.5是老版本,现在的版本是10.5.8(从10.5.5开始内部有很多变化),所以你真的应该考虑升级。对于 Indy 11,Indy 的 MIME 解析代码将被重构和泛化,以便更容易地重用。目前,它主要是为电子邮件解析而设计的,在其他情况下使用它需要大量的手动工作(但可以完成),例如 HTTP 上传。
【解决方案2】:

我开始 xxm 是为了使用 Delphi 构建网站,并在进行更改后通过按下浏览器的刷新按钮来重新编译包含 HTML 和 Pascal 代码的脚本。

它使用“插入”IIS、Apache、Internet Explorer、FireFox 的通用接口,还有一个独立的 HTTP exe。上传文件时,接口会在参数上公开 IxxmParameterPostFile。

有关示例,请参阅 demo 4 Upload

【讨论】:

  • 这不是真正的问题,而是当场,非常好的项目,我不敢相信我以前没有见过它。是否有可能将其移植到“Free Pascal”以获得跨平台支持?我目前没有足够的时间“玩”,但我一定会在接下来的几周内给予 XXM 更多的关注。
  • 移植到 FreePascal 取决于一个像样的 ComServ.pas,我每次检查时都缺少它。我可以尝试创建一个开源 ComServ.pas,如果我拥有全世界所有的时间和金钱......
  • 我觉得你是 Stijn,即使我现在无法切换到 XXM,这是最接近我的问题的选项,谢谢!
【解决方案3】:

Only suitable solution I can find 未经个人测试(如果这不能让您找到满足您需求的可行解决方案,请告诉我,我会启动 XE 并产生更雄辩的东西)

【讨论】:

  • 只是一个 FYI,其中的活动部分是创建一个 TStream(TFileStream 或 TMemoryStream),然后调用 IdHTTP1.Post(, );
  • 这不是我需要的,看到问题是浏览器发送的数据也需要从MIME解码为二进制。
  • 啊...可能值得调整您的问题以澄清该要求:)
  • 抱歉,我对自己无法完成这个相对简单的任务感到有点沮丧......问题已更新。
  • 好吧,我们不能总是靠自己解决所有问题……否则 StackOverflow 就不会存在,不是吗? :P
【解决方案4】:

http://www.synaptica.info/2014/01/31/tidhttpserver-decode-content-type-multipartform-data/

我像这样进行简单的分段上传:

使用单位:

interface
uses
  System.SysUtils, System.Classes, Web.Win.Sockets, IdBaseComponent,
  IdComponent, IdCustomTCPServer, IdCustomHTTPServer, IdHTTPServer, IdContext,
  IdTCPServer,System.Generics.Collections, Data.DB, Datasnap.DBClient,IdHeaderList,idGlobal,
  IdIntercept,IdMessage,IdMessageCoderMIME,IdMessageCoder,IdGlobalProtocols;

在 mime 内容上循环的代码:

procedure TdmNet.IdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
Var
  ms : TMemoryStream;
  newdecoder, Decoder: TIdMessageDecoder;
  boundary, startboundary : String;
  msgEnd : Boolean;
  tmp : String;
  I : Integer;
  fname : String;
  tsValues : TStringList;

begin
  i := 0;


  if pos('upload',lowercase(ARequestInfo.Document)) > 0 then
   begin
    If ARequestInfo.PostStream = nil then

      AResponseInfo.ContentText := '<HTML><BODY>unparsed:' + ARequestInfo.UnparsedParams +
      '<br>Encoding:' + ARequestInfo.ContentEncoding + ARequestInfo.RawHeaders.Values['Content-Type'] +
      '<br>HashCode:' + IntToStr(ARequestInfo.GetHashCode) +
      '<br>Params:' + ARequestInfo.Params.Text + ' -->stream nullo<br></BODY><HTML>'
    Else
      ARequestInfo.PostStream.Position := 0;
      msgEnd := False;


      boundary := ExtractHeaderSubItem(ARequestInfo.ContentType, 'boundary',QuoteHTTP);
      startboundary := '--' + boundary;
      repeat
        tmp := ReadLnFromStream(ARequestInfo.PostStream, -1, True);
      until tmp = startboundary;

      decoder := TIdMessageDecoderMIME.Create(nil);
      TIdMessageDecoderMIME(decoder).MIMEBoundary := boundary;
      tsValues := TStringList.Create;

      try
          repeat
           decoder.SourceStream := ARequestInfo.PostStream;
           decoder.FreeSourceStream := false;
           decoder.ReadHeader;
           inc(I);
           case Decoder.PartType of
            mcptAttachment,mcptText : begin

                              ms := TMemoryStream.Create;
                              ms.Position := 0;
                              newdecoder := Decoder.ReadBody(ms,msgEnd);
                              tmp := Decoder.Headers.Text;
                              fname := decoder.Filename;
                              decoder.Free;
                              decoder := newdecoder;
                              if decoder <> nil then
                                TIdMessageDecoderMIME(decoder).MIMEBoundary := boundary;
                              sleep(100);
                              if fname <> '' then
                               begin
                                 ms.SaveToFile(fname);

                                 //msgEnd := true;
                               end
                              else
                               begin
                                ms.SaveToFile(inttostr(i) + '.txt');
                               end;
                              ms.Free;
                             end;
            mcptIgnore: Begin
                        try
                          FreeAndNil(decoder);
                          decoder := TIdMessageDecoderMIME.Create(nil);
                          TIdMessageDecoderMIME(decoder).MIMEBoundary := boundary;
                        finally
                          ms.Free;
                        end;
                      End;
            mcptEOF: begin FreeAndNil(decoder); msgEnd := True end;
           end;

          until (decoder = nil) or(msgEnd);
      finally
       if decoder <> nil then
        decoder.Free;

      end;


      AResponseInfo.ContentText := AResponseInfo.ContentText  + '</BODY><HTML>';

      AResponseInfo.ContentText := '<HTML><BODY>unparsed:' + ARequestInfo.UnparsedParams +
      '<br>Encoding:' + ARequestInfo.ContentEncoding + '<br>Conte' +  ARequestInfo.RawHeaders.Values['Content-Type'] +
      '<br>HashCode:' + IntToStr(ARequestInfo.GetHashCode) +
      '<br>Params:' + ARequestInfo.Params.Text + ' -->stream nullo<br></BODY><HTML>';
   end
  Else
   Begin
     AResponseInfo.ContentText :=
    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">   ' + #10#13 +
    '<html xmlns="http://www.w3.org/1999/xhtml">                                                                                 ' + #10#13 +
    '<head>                                                                                                                      ' + #10#13 +
    '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />                                                       ' + #10#13 +
    '<title>Pagina di prova</title>                                                                                               ' + #10#13 +
    '</head>                                                                                                                     ' + #10#13 +
    '                                                                                                                            ' + #10#13 +
    '<body>                                                                                                                      ' + #10#13 +
    '<h1>Test multipart from <a href="www.synaptica.info">Synaptica Srl</a>  </h1> <BR><BR>                                                        ' + #10#13 +
    '<form action="upload" method="post"  enctype="multipart/form-data">                                                                                               ' + #10#13 +
    '<p>key                                                                                                                      ' + #10#13 +
    '  <input type="text" name="key" id="key" />                                                                                 ' + #10#13 +
    '</p>                                                                                                                        ' + #10#13 +
     '<p>group                                                                                                                      ' + #10#13 +
    '  <input type="text" name="group" id="key" />                                                                                 ' + #10#13 +
    '</p>                                                                                                                        ' + #10#13 +
    '                                                                                                                            ' + #10#13 +
    '<label for="file">Filename:</label>                                                                                         ' + #10#13 +
    '<label for="file">'  +   ARequestInfo.Document +  '</label>                                                                                         ' + #10#13 +
    '<input type="file" name="file" id="file" />                                                                                 ' + #10#13 +
    '<br />                                                                                                                      ' + #10#13 +
    '<input type="submit" name="submit" value="Submit" />                                                                        ' + #10#13 +
    '</form></p>                                                                                                                  ' + #10#13 +
    '</body>                                                                                                                     ' + #10#13 +
    '</html>                                                                                                                     ';
   End;

【讨论】:

    【解决方案5】:

    在我看来,这是一个长期存在的问题。我查看了互联网上的各种建议,没有任何东西可以与 MsMultipartparser.pas 相提并论。遗憾的是,它不适用于 Unicode。

    为什么没有比我聪明得多的人重写 MsMultipartparser.pas 并为我们大家省去很多麻烦?

    印地 - 不工作。

    IPWorks - 似乎只是给你文件名等等。无法弄清楚如何获取文件本身。

    Alcinoe - 没有安装说明,更不用说解释,而且似乎不适用于 XE8 或 Delphi 10

    我查看了其他几个,但它们都是不切实际的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 1970-01-01
      • 1970-01-01
      • 2015-12-26
      相关资源
      最近更新 更多