首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >恢复HTTP / Indy上传

恢复HTTP / Indy上传
EN

Stack Overflow用户
提问于 2012-03-07 08:49:00
回答 1查看 9.1K关注 0票数 3

我试图使用indy (HTTP )恢复上传,代码如下(使用Delphi2010,Indy 10.4736):

代码语言:javascript
复制
 IdHttp.Head('http://localhost/_tests/resume/large-file.bin');
 ByteRange           := IdHttp.Response.ContentLength + 1;

 // Attach the file to post/upload
 Stream              := TIdMultipartFormDataStream.Create;
 with Stream.AddFile('upload_file', 'D:\large-file.bin', 'application/octet-stream') do
 begin
      HeaderCharset  := 'utf-8';
      HeaderEncoding := '8';
 end;    // with

 with IdHTTP do
 begin
      IOHandler.LargeStream           := True;

      with Request do
      begin
           ContentRangeStart          := ByteRange;
           ContentRangeEnd            := (Stream.Size - ByteRange);
           ContentLength              := ContentRangeEnd;
           ContentRangeInstanceLength := ContentLength;
      end;    // with

      Post('http://localhost/_tests/resume/t1.php', Stream);
 end;    // with

但是上传简历不起作用:

我查看了Indy的代码,似乎这个函数在IdIOHandler.pas

TIdIOHandler.Write()

始终处理完整的流/文件(因为参数ASize: TIdStreamSize似乎总是0,根据代码,这意味着发送完整的文件/流)。

这样可以防止indy继续上传。

我的问题是:是否有可能避免发送完整的文件?

设置内容范围没有改变任何事情。我还修改了indy的代码(修改了3行),以使indy服从内容范围/流位置,但是它是错误的,并且indy总是挂在IdStackWindows.pas中,因为这里有一个无限的超时:

TIdSocketListWindows.FDSelect()

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-07 10:55:53

正如我在your earlier question中告诉您的,您必须发布一个包含要上载的剩余文件数据的TStream。不要使用TIdMultipartFormDataStream.AddFile(),因为这将发送整个文件。改用TStream重载版本的TIdMultipartFormDataStream.AddFormField()

TIdHTTP并不是为了尊重ContentRange...属性而设计的。大多数Request属性仅设置相应的headers,它们不影响数据。这就是为什么你的编辑破坏了它。

试试这个:

代码语言:javascript
复制
IdHttp.Head('http://localhost/_tests/resume/large-file.bin');
FileSize := IdHttp.Response.ContentLength;

FileStrm := TFileStream.Create('D:\large-file.bin', fmOpenRead or fmShareDenyWrite);
try
  if FileSize < FileStrm.Size then
  begin
    FileStrm.Position := FileSize;

    Stream := TIdMultipartFormDataStream.Create;
    try
      with Stream.AddFormField('upload_file', 'application/octet-stream', '', FileStrm, 'large-file.bin') do
      begin
        HeaderCharset  := 'utf-8';
        HeaderEncoding := '8';
      end;

      with IdHTTP do
      begin
        with Request do
        begin
          ContentRangeStart := FileSize + 1;
          ContentRangeEnd   := FileStrm.Size;
        end;

        Post('http://localhost/_tests/resume/t1.php', Stream);
      end;
    finally
      Stream.Free;
    end;
  end;
finally
  FileStrm.Free;
end;

尽管如此,这是一个严重滥用的HTTP和multipart/form-data。首先,ContentRange值位于错误的位置。您正在将它们应用于整个Request,这是错误的。它们需要在FormField上应用,但是TIdMultipartFormDataStream目前不支持这一点。第二,multipart/form-data的设计并不是为了像这样使用。从一开始上传一个文件是可以的,但是不能恢复一个坏的上传。您真的应该停止使用TIdMultipartFormDataStream,直接将文件数据像i suggested earlier那样传递给TIdHTTP.Post(),例如:

代码语言:javascript
复制
FileStrm := TFileStream.Create('D:\large-file.bin', fmOpenRead or fmShareDenyWrite);
try
  IdHTTP.Post('http://localhost/_tests/upload.php?name=large-file.bin', FileStrm);
finally
  FileStrm.Free;
end;

代码语言:javascript
复制
IdHTTP.Head('http://localhost/_tests/files/large-file.bin');
FileSize := IdHTTP.Response.ContentLength;

FileStrm := TFileStream.Create('D:\large-file.bin', fmOpenRead or fmShareDenyWrite);
try
  if FileSize < FileStrm.Size then
  begin
    FileStrm.Position := FileSize;
    IdHTTP.Post('http://localhost/_tests/resume.php?name=large-file.bin', FileStrm);
  end;
finally
  FileStrm.Free;
end;

我已经知道如何在explained earlier中访问原始的POST数据。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9598273

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档