实际上我正在使用TIdHTTP组件从互联网上下载文件.我想知道是否可能暂停并使用此组件恢复下载o也许是另一个indy组件.
这是我目前的代码,这适用于下载文件(没有恢复),但是.现在我想暂停下载关闭我的应用程序,当我的应用程序重新启动后,从最后保存的位置恢复下载.
var
Http: TIdHTTP;
MS : TMemoryStream;
begin
Result:= True;
Http := TIdHTTP.Create(nil);
MS := TMemoryStream.Create;
try
try
Http.OnWork:= HttpWork;//this event give me the actual progress of the download process
Http.Head(Url);
FSize := Http.Response.ContentLength;
AddLog('Downloading File '+GetURLFilename(Url)+' - '+FormatFloat('#,',FSize)+' Bytes');
Http.Get(Url, MS);
MS.SaveToFile(LocalFile);
except
on E : Exception do
Begin
Result:=False;
AddLog(E.Message);
end;
end;
finally
Http.Free;
MS.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
以下代码对我有用.它按块下载文件:
procedure Download(Url,LocalFile:String;
WorkBegin:TWorkBeginEvent;Work:TWorkEvent;WorkEnd:TWorkEndEvent);
var
Http: TIdHTTP;
exit:Boolean;
FLength,aRangeEnd:Integer;
begin
Http := TIdHTTP.Create(nil);
fFileStream:=nil;
try
try
Http.OnWork:= Work;
Http.OnWorkEnd := WorkEnd;
Http.Head(Url);
FLength := Http.Response.ContentLength;
exit:=false;
repeat
if not FileExists(LocalFile) then begin
fFileStream := TFileStream.Create(LocalFile, fmCreate);
end
else begin
fFileStream := TFileStream.Create(LocalFile, fmOpenReadWrite);
exit:= fFileStream.Size >= FLength;
if not exit then
fFileStream.Seek(Max(0, fFileStream.Size-4096), soFromBeginning);
end;
try
aRangeEnd:=fFileStream.Size + 50000;
if aRangeEnd < fLength then begin
Http.Request.Range := IntToStr(fFileStream.Position) + '-'+ IntToStr(aRangeEnd);
end
else begin
Http.Request.Range := IntToStr(fFileStream.Position) + '-';
exit:=true;
end;
Http.Get(Url, fFileStream);
finally
fFileStream.Free;
end;
until exit;
Http.Disconnect;
except
on E : Exception do
Begin
//Result:=False;
//AddLog(E.Message);
end;
end;
finally
Http.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
也许 HTTP RANGE 标头可以在这里帮助您。请查看archive.org 的 http://www.west-wind.com/Weblog/posts/244.aspx 副本,了解有关恢复 HTTP 下载的更多信息:
( 2004-02-07 ) 几天前,留言板上有人问了一个有趣的问题,关于如何提供可断点续传的HTTP 下载。我对这个问题的第一反应是,这是不可能的,因为 HTTP 是一种无状态协议,没有文件指针的概念,因此无法恢复 HTTP 下载。
然而事实证明,HTTP 1.1 确实能够通过使用从客户端发送的 Http 标头中的 Range: 标头来指定下载范围。您可以执行以下操作:
Run Code Online (Sandbox Code Playgroud)Range: 0-10000 Range: 100000- Range: -100000下载前 100000 字节、超过 100000 字节的所有内容或最后 100000 字节。还有更多组合,但前两种是可恢复下载感兴趣的组合。
为了演示此功能,我使用 wwHTTP(在 Web Connection/VFP 中)将文件的前 400k 块下载到带有 HTTPGetEx 的文件中,这旨在模拟中止的下载。接下来,我执行第二个请求来获取现有文件并下载其余文件:
Run Code Online (Sandbox Code Playgroud)#INCLUDE wconnect.h CLEAR CLOSE DATA DO WCONNECT LOCAL o as wwHTTP lcDownloadedFile = "d:\temp\wwipstuff.zip" *** Simulate partial output lcOutput = "" Text="" tnSize = 0 o = CREATEOBJECT("wwHTTP") o.HttpConnect("www.west-wind.com") ? o.httpgetex("/files/wwipstuff.zip",@Text,@tnSize,"Range: bytes=0-400000"+CRLF,lcDownloadedFile) o.Httpclose() lcOutput = Text ? LEN(lcOutput) *** Figure out how much we downloaded lnOpenAt = FILESIZE(lcDownloadedFile) *** Do a partial download starting at this byte count Text="" tnSize =0 o = CREATEOBJECT("wwHTTP") o.HttpConnect("www.west-wind.com") ? o.httpgetex("/files/wwipstuff.zip",@Text,@tnSize,"Range: bytes=" + TRANSFORM(lnOpenAt) + "-" + CRLF) o.Httpclose() ? LEN(Text) *** Read the existing partial download and append current download lcOutput = FILETOSTR(lcDownloadedFile) + TEXT ? LEN(lcOutput) STRTOFILE(lcOutput,lcDownloadedFile) RETURN请注意,此方法使用磁盘上的文件,因此您必须使用 HTTPGetEx(带有 Web 连接)。如果您选择,第二次下载也可以完成到磁盘,但是如果您有多个中止并且需要将它们拼凑在一起,事情就会变得棘手。在这种情况下,您可能想要尝试跟踪每个文件并向其添加一个数字,然后在最后合并结果。
如果您使用 WinInet 下载到内存(这是 wwHTTP 在幕后使用的),您还可以尝试从临时 Internet 文件缓存中剥离该文件。虽然这有效,但我怀疑这个过程很快就会变得非常复杂,因此如果您计划提供恢复功能,我强烈建议您使用上述方法将输出写入文件。
有关 WinInet 的一些附加信息以及使用此方法的一些要求如下所述: http: //www.clevercomponents.com/articles/article015/resuming.asp。
通过将 Range 标头添加到 wwHTTP:WebRequest.Headers 对象,可以对 .Net 的 wwHTTP 完成相同的操作。
( Randy Pearson ) 假设您不知道服务器上的文件大小是多少。有没有办法找到这个问题,例如,您可以知道要请求多少块?您会先发送 HEAD 请求,还是 GET 响应的标头也告诉您总大小?
( Rick Strahl ) 您必须读取 Content-Length: 标头才能获取下载文件的大小。如果您要恢复,这应该不重要 - 您只需使用 Range: (existingsize) - 即可获得其余内容。对于大块下载,您可以读取内容长度并仅下载前 x 个字节。对于 wwHTTP,这会变得很棘手 - 您必须使用 HTTPGetEx 进行单独的调用,并将 tnBufferSize 参数设置为要检索的块大小,以使其在达到大小后停止。
( Randy Pearson ) 后续: 看起来兼容的服务器会向您发送足够的信息来了解大小。如果它提供块,它应该回复如下内容:
Run Code Online (Sandbox Code Playgroud)Content-Range: 0-10000/85432因此您可以(如果需要)提取它并在循环中使用它来继续智能块请求。
另请参阅此处https://forums.embarcadero.com/message.jspa?messageID=219481,了解同一主题的 TIdHTTP 相关讨论:
(至少部分按照 tfilestream.seek 和偏移量混淆)
Run Code Online (Sandbox Code Playgroud)if FileExists(dstFile) then begin Fs := TFileStream.Create(dstFile, fmOpenReadWrite); try Fs.Seek(Max(0, Fs.Size-1024), soFromBeginning); // alternatively: // Fs.Seek(-1024, soFromEnd); Http.Request.Range := IntToStr(Fs.Position) + '-'; Http.Get(Url, Fs); finally Fs.Free; end; end;
| 归档时间: |
|
| 查看次数: |
4452 次 |
| 最近记录: |