Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 使用Indy下载文件时,从一开始就指定完整大小_Delphi_Download_Delphi 2010_Indy_Indy10 - Fatal编程技术网

Delphi 使用Indy下载文件时,从一开始就指定完整大小

Delphi 使用Indy下载文件时,从一开始就指定完整大小,delphi,download,delphi-2010,indy,indy10,Delphi,Download,Delphi 2010,Indy,Indy10,我有这个delphi代码,基本上下载一个文件(使用delphi 2010+Indy 10.5.8 r4743),一切正常,除了当我下载100Mb(例如)时,Indy似乎分配了完整的大小(即立即创建一个包含100Mb虚拟内容(*)的文件),然后下载该文件 最后100MB被正确下载,但由于下载过程是在后台使用隐藏的可执行文件完成的,因此我的代码基于临时文件大小来更新主UI with IdHTTP do begin if FileExists(LocalFile) then

我有这个delphi代码,基本上下载一个文件(使用delphi 2010+Indy 10.5.8 r4743),一切正常,除了当我下载100Mb(例如)时,Indy似乎分配了完整的大小(即立即创建一个包含100Mb虚拟内容(*)的文件),然后下载该文件

最后100MB被正确下载,但由于下载过程是在后台使用隐藏的可执行文件完成的,因此我的代码基于临时文件大小来更新主UI

with IdHTTP do
begin
     if FileExists(LocalFile) then
        iLength     := FileSize2(LocalFile)
     else
         iLength    := 0;

     DoExit         := False;
     try
        try
           repeat
                 if ExitApp then
                    Exit;

                 if Not FileExists(LocalFile) then
                    AFileStream     := TFileStream.Create(LocalFile, fmCreate)
                 else
                 begin
                      // File already exist, resume download
                      AFileStream   := TFileStream.Create(LocalFile, fmOpenReadWrite);
                      DoExit        := (AFileStream.Size >= iLength);
                      if (Not DoExit) then
                         AFileStream.Seek(Max(0, AFileStream.Size - 4096), soFromBeginning);
                 end;

                 iRangeEnd          := AFileStream.Size + 50000;

                 if (iRangeEnd < iLength) then
                    Request.Range   := IntToStr(AFileStream.Position) + '-' + IntToStr(iRangeEnd)
                 else
                 begin
                      Request.Range := IntToStr(AFileStream.Position) + '-';
                      DoExit        := True;
                 end;

                 PostTime           := Now;
                 Get(TheURL, AFileStream);
                 IsError            := Not (ResponseCode in [200, 206]);
           until DoExit;

           Disconnect;
        except
              IsError               := True;
        end;    // try/except
     finally
            FreeAndNil(AFileStream);
     end;    // try/finally
end;    // with
使用IdHTTP-do
开始
如果文件存在(LocalFile),则
iLength:=文件大小2(本地文件)
其他的
i长度:=0;
DoExit:=假;
尝试
尝试
重复
如果退出,那么
出口
如果文件不存在(LocalFile),则
AFileStream:=TFileStream.Create(LocalFile,fmCreate)
其他的
开始
//文件已存在,请继续下载
AFileStream:=TFileStream.Create(LocalFile,fmOpenReadWrite);
DoExit:=(AFileStream.Size>=ilelength);
如果(不是DoExit)那么
Seek(最大值(0,AFileStream.Size-4096),从开始到结束);
结束;
iRangeEnd:=AFileStream.Size+50000;
如果(iRangeEnd
我的问题是有没有办法避免印地的这种行为?我知道我可以使用OnWork事件,但是我需要跟踪文件名

理想情况下,我也希望避免IPC(有点过分了+我不想使用它,比如说每秒,对于多次下载,我非常喜欢使用文件大小作为下载进度的指示,因为它在更新UI时提供了更多的自由度)


(*)我假设它是虚拟内容,因为我需要60-100秒的当前internet连接速度才能真正获取文件

是,
TIdHTTP
根据HTTP响应头预先分配完整文件大小(如果它提前知道大小)。这是一种优化技术。预分配文件可避免在写入较大文件时产生不必要的文件系统开销,因为文件不必随着时间的推移而不断增长,从而在HDD上寻找可用扇区,从而减慢写入过程。目前没有办法禁用预分配,这是Indy内部的硬编码行为。因此,依赖文件的实际大小作为进度指示器对您来说是行不通的。你必须将实际进度信息从后台应用程序传送到主应用程序。

谢谢你,雷米……虽然我理解这一决定背后的原因,但这使得暂停/恢复下载变得很困难(如果不是不可能的话),因为我无法知道恢复字节/偏移量。我意识到这是一个不同的问题(源于原始问题),但我想知道是否有解决方案?您必须使用
OnWork…
事件来跟踪实际进度,然后在下载中断时将磁盘上的文件截断为最后已知的大小。
TIdHTTP
不会预先分配文件的唯一时间是使用
chunked
传输编码发送数据,在这种情况下,
TIdHTTP
不会提前被告知文件大小(因为服务器本身可能不知道)。Indy的源代码中已经有一条TODO注释,可以将预分配作为可选功能,但是没有关于何时实现的ETA。谢谢你,Remy,是的,这就是我正在做的,我正在考虑编写*.progress文件,以便在硬崩溃后恢复,希望这对meRemy有效,我想(我将下载信息存储在数据库中),唯一的问题是,当恢复时(崩溃后),
a工作计数
反映当前会话字节计数,但它不考虑以前下载的字节(在应用程序崩溃之前)。是否有办法在OnWork()中获取总的
下载字节位置
来自Indy本身的事件(即
TIdHTTP(Sender).CurrentPosition
或类似的东西)?因此在主文件旁边写一个“filename.zip.progress”文本文件。:-)是的,这正是我所做的!