我正在尝试使用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()
答案 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;
数据。