使用Indy恢复HTTP发布/上传

时间:2012-03-07 08:49:00

标签: delphi post upload indy resume

我正在尝试使用indy(HTTP Post)恢复上传,代码看起来像这样(使用Delphi 2010,Indy 10.4736):

 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服从内容范围/流的位置,但它的bug和indy总是最终挂在 IdStackWindows.pas ,因为这里有无限超时:< / p>

  

TIdSocketListWindows.FDSelect()

1 个答案:

答案 0 :(得分:4)

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

并且TIdMultipartFormDataStream.AddFormField()并非旨在尊重TIdHTTP属性。大多数ContentRange...属性仅仅设置了相应的HTTP标头,它们不会影响数据。这就是为什么你的编辑打破了它。

试试这个:

Request

据说,这是HTTP和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; GROSS MISUSE 。首先,multipart/form-data值位于错误的位置。您将它们作为一个整体应用于整个ContentRange,这是错误的。它们需要在Request处应用,但FormField目前不支持。其次,TIdMultipartFormDataStream并不是设计成像这样使用。它可以从一开始就上传文件,但不能用于恢复损坏的上传。你真的应该停止使用multipart/form-data并将文件数据直接传递给TIdMultipartFormDataStream,例如:suggested earlier,例如:

TIdHTTP.Post()

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;

我已经explained earlier如何访问PHP中的原始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; 数据。