Delphi:下载更新文件期间的问题,与Indy(TidHttp)

时间:2015-07-16 13:17:41

标签: delphi download indy idhttp

  • Q1:为什么在下载过程中无法关闭模态表单
  • Q2:为什么下载完成后进度条不会100%丰富(这是一种重绘方式?)
  • 问题3:为什么我在此期间停止并重新启动与Web服务器的连接 下载传输正在停止而不指示任何错误和 从不继续?我该怎么做以获取并捕获错误并继续 回到初始状态(下载并安装进度条at 位置0)

备注:IdAntiFreeze已激活

procedure Tform_update.button_downloadClick(Sender: TObject);
var
  FS: TFileStream;
  url, file_name: String;
begin
  //execute download
  if button_download.Tag = 0 then
    begin
      Fdone:= False;
      Fcancel:= False;

      url:= APP_DOMAIN + '/downloads/Setup.exe';
      file_name:= 'C:\Temp\Setup.exe';

      if FileExists(file_name) then DeleteFile(file_name);

      try
        FS:= TFileStream.Create(file_name, fmCreate);
        Http:= TIdHTTP.Create(nil);

        Http.OnWorkBegin:= HttpWorkBegin;
        Http.OnWork:= HttpWork;

        Http.Get(url, FS);
      finally
        FS.Free;
        Http.Free;
        if Fdone then ModalResult:= mrOk;
      end;
    end
  else
    //cancel download
    begin
      Fcancel:= True;
    end;
end;

procedure Tform_update.HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  ContentLength: Int64;
  Percent: Integer;
begin
  ContentLength:= Http.Response.ContentLength;
  if AWorkCount = ContentLength then Fdone:= True; //

  if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and (ContentLength > 0) then
    begin
      sleep(15);
      Percent := 100 * AWorkCount div ContentLength;
      progress_bar.Position:= Percent;
    end;

  //stop download
  if Fcancel and Http.Connected then
    begin
      Http.IOHandler.InputBuffer.Clear;
      Http.Disconnect;
      Fcancel:= False;

      button_download.Caption:= _('Download and Install');
      button_download.Tag:= 0;
      progress_bar.Position:= 0;
    end;
end;

procedure Tform_update.HttpWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  if AWorkMode <> wmRead then Exit;

  button_download.Tag:= 1;
  button_download.Caption:= _('Cancel');
end;

procedure Tform_update.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Fcancel:= True;
end;

3 个答案:

答案 0 :(得分:1)

另一种方法是使用TThread来控制执行。像这样:

  ThreadUpdate = class(TThread)
  protected
    procedure Execute; override;
  public

procedure ThreadUpdate.Execute;
begin
  inherited;
  while (not terminated) do 
  begin
      //YOUR CODE HERE - maybe your button_download Click
      Terminate;
  end;
end;   

此外,您可以尝试让Windows处理您应用的消息。

  if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and (ContentLength > 0) then
  begin
    sleep(15);
    Percent := 100 * AWorkCount div ContentLength;
    progress_bar.Position:= Percent;
    **Application.ProcessMessages;**
  end;

答案 1 :(得分:1)

Q1。 Indy正在阻止。所有Antifreeze都会定期调用Windows消息处理。它并没有阻止Indy的阻塞性质,所以除非你明确地有办法处理错误,否则它不会表现出你想要的行为。您需要在不同的线程中进行下载,并使用您的表单来监视该线程的状态,而不是尝试依赖防冻。不要在该线程中放置任何UI操作,将它们保留在主线程中,因此不要尝试从线程内更新进度条。例如,将同步变量设置为进度百分比,并从主线程中的计时器读取该变量。请记住,UI组件不是线程安全的,因此只能从单个线程更新。

Q2。我也见过这个。与Indy无关。我认为当你将状态栏设置为100%时,组件不会立即响应,但会尝试顺利移动到那一点(但没有时间)。不过,这只是猜测。我不确定。或者它可能是我猜的防冻处理消息的频率(在这种情况下它与Indy有关)。

Q3。与Q1完全相同,采用相同的解决方案。放入一个单独的线程,并从主线程监视该线程的状态。

将Indy操作移动到单独的线程后,您不需要Antifreeze。

答案 2 :(得分:0)

关于Q1和Q2,线程肯定更好。如果您决定继续使用Indy Antifreeze,则应确保将OnlyWhenIdle标志设置为False,以便它可以在工作完成时处理消息。