Indy FTP无法正确加载进度条。

4

我的一个朋友向我求助,因为他想要一个进度条来指示一些文本文件的上传/下载。这里是我使用的代码:

procedure TForm1.IdFTP1Work(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin
 Application.ProcessMessages;
 ProgressBar1.Position:= AWorkCount;
 Label6.Caption:=IntToStr(ProgressBar1.Position);
end;

procedure TForm1.IdFTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Int64);
begin
 if(AWorkCountMax>0) then
  begin
    ProgressBar1.Max:=AWorkCountMax;
  end;
  ProgressBar1.Position:=0;
end;

procedure TForm1.IdFTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
 ProgressBar1.Position:=0;
end;

在我的表单上,我还有两个标签: 第一个指示进度,称为Label6,另一个简单地带有标题,如“%”,如下所示。 Label 6 应该有从0到100的值。 enter image description here 他发送的文本文件现在很小,但它们将会变得更大。我的问题是,我在程序中看不到进度条(绿色矩形),而且标签6上的值超过100,达到了700。我该怎么办?

也许可以尝试这样写:ProgressBar1.Position:= AWorkCount; Application.ProcessMessages; 我认为在设置 ProgressBar 的位置之后应该调用 ProcessMessages。 - Bill
1个回答

9
AWorkCountMaxAWorkCount是字节计数,而不是百分比。在更新UI时需要考虑到这一点,特别是如果您想显示百分比。需要注意的是,在上传过程中才会使用AWorkCountMax,而在下载过程中则不会。原因是FTP协议在传输过程中不会传输文件大小,因此TIdFTP无法知道正在下载的文件大小,只能知道正在上传的本地文件大小。如果要下载文件,则需要先手动检索文件大小,可以使用TIdFTP.Size()TIdFTP.List()TIdFTP.ExtListItem()
另外,请避免使用Application.ProcessMessages()。如果您想触发重绘,请改用Update()
请尝试以下内容:
procedure TForm1.IdFTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  if AWorkMode = wmWrite then
    ProgressBar1.Max := AWorkCountMax
  else;
    ProgressBar1.Max := ...; // value retrieved beforehand...
  ProgressBar1.Position := 0;
end;

procedure TForm1.IdFTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  if ProgressBar1.Max > 0 then
  begin
    ProgressBar1.Position := AWorkCount;
    Label6.Caption := IntToStr((ProgressBar1.Position * 100) div ProgressBar1.Max) + '%';
  end else
    Label6.Caption := IntToStr(AWorkCount) + ' bytes';
  Update;
end;

procedure TForm1.IdFTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
  ProgressBar1.Position := 0;
end;

或者:

var
  WorkMax: Int64;

procedure TForm1.IdFTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  if AWorkMode = wmWrite then
    WorkMax := AWorkCountMax
  else;
    WorkMax := := ...; // value retrieved beforehand...
  ProgressBar1.Min := 0;
  ProgressBar1.Max := 100;
  ProgressBar1.Position := 0;
end;

procedure TForm1.IdFTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  if WorkMax > 0 then
  begin
    ProgressBar1.Position := (AWorkCount * 100) div WorkMax;
    Label6.Caption := IntToStr(ProgressBar1.Position) + '%';
  end else
    Label6.Caption := IntToStr(AWorkCount) + ' bytes';
  Update;
end;

procedure TForm1.IdFTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
  ProgressBar1.Position := 0;
end;

那么您的意思是,下载过程中不应该使用 AWorkCountMax,而应该使用像 a:=TIdFTP.Size() 这样的方法? - Alberto Miola
2
是的,但在调用Get()之前需要先调用Size()。您不能在传输过程中进行调用。请记住,并不是所有服务器都支持SIZE命令,这就是为什么我提到了其他可替代的方法。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接