Windows 在Delphi中下载文件

Windows 在Delphi中下载文件,windows,delphi,winapi,download,Windows,Delphi,Winapi,Download,谷歌搜索展示了一些如何在Delphi中下载文件的例子,但大多数都有问题,根据我的经验,有一半的时间不起作用 我正在寻找一个简单健壮的解决方案,它可以让我下载一个exe(用于更新我的应用程序),并在下载完成或出错之前保持当前更新线程的执行。这个过程已经线程化了,所以下载代码应该一直保持执行直到完成(希望如此) 这里有两个实现,它们看起来都非常复杂 1. 2. 第二种方法是使用WinINet(Windows API的一部分)使用Internet资源的标准方法。我经常使用它,而且一直效果很好。我从

谷歌搜索展示了一些如何在Delphi中下载文件的例子,但大多数都有问题,根据我的经验,有一半的时间不起作用

我正在寻找一个简单健壮的解决方案,它可以让我下载一个exe(用于更新我的应用程序),并在下载完成或出错之前保持当前更新线程的执行。这个过程已经线程化了,所以下载代码应该一直保持执行直到完成(希望如此)

这里有两个实现,它们看起来都非常复杂
1.

2.

第二种方法是使用WinINet(Windows API的一部分)使用Internet资源的标准方法。我经常使用它,而且一直效果很好。我从未尝试过的第一种方法。(两者都不是“非常复杂”。在使用Windows API时,总会有一些额外的步骤。)

如果您想要一个非常简单的方法,您可以简单地调用。您将无法(完全)控制下载,但它非常简单

例如:

URLDownloadToFile(nil,
                  'http://www.rejbrand.se',
                  PChar(ExtractFilePath(Application.ExeName) + 'download.htm'),
                  0,
                  nil);

为什么不利用印地。如果您使用TIdHTTP,那么它很简单

procedure DownloadFile;    
var
  IdHTTP1: TIdHTTP;
  Stream: TMemoryStream;
  Url, FileName: String;
begin    
  Url := 'http://www.rejbrand.se';
  Filename := 'download.htm';

  IdHTTP1 := TIdHTTP.Create(Self);
  Stream := TMemoryStream.Create;
  try
    IdHTTP1.Get(Url, Stream);
    Stream.SaveToFile(FileName);
  finally
    Stream.Free;
    IdHTTP1.Free;
  end;
end;
您甚至可以使用OnWork和OnWorkBegin事件添加进度条

procedure IdHTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode;AWorkCountMax: Int64);
begin
  ProgressBar.Max := AWorkCountMax;
  ProgressBar.Position := 0;
end;

procedure IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
  ProgressBar.Position := AWorkCount;
end;
我不确定这些事件是否在主线程的上下文中触发,因此,对VCL组件所做的任何更新都可能必须使用tidnotify组件来避免线程问题。也许其他人可以检查一下

使用URLMon

errcode := URLMon.URLDownloadToFile(nil,
                      PChar('http://www.vbforums.com/showthread.php?345726-DELPHI-Download-Files'),
PChar( 'a:\download.htm'),
      0,
      nil);
if errcode > 0 then
      showmessage('Error while downloading: ' + inttostr(errcode));

对于具有更高版本delphi的用户,您可以使用:

var
  http : TNetHTTPClient;
  url : string;
  stream: TMemoryStream;
begin
  http := TNetHTTPClient.Create(nil);
  stream := TMemoryStream.Create;
  try
    url := YOUR_URL_TO_DOWNLOAD;
    http.Get(url, stream);
    stream.SaveToFile('D:\Temporary\1.zip');
  finally
    stream.Free;
    http.Free;
  end;
end;

提示:用
ParamStr(0)
替换
Application.ExeName
,以删除对
表单
单元的依赖关系。@mjustin:True。但在生产代码中,您无论如何都不希望将文件保存到应用程序的目录中,该目录是只读的(程序文件),除非该程序是可移植的(例如,在U盘上运行)。谢谢您的回答Andreas。我采用了我发布的第二种方法,因为你说这是标准,希望它是可靠的。谢谢你的努力。谢谢@AndreasRejbrand!这正是我要找的!记住这一点;internet Explorer下载历史记录不允许您下载正在下载的文件的最新版本。。因此,使用IE api可能更快,但并不是在所有情况下下载文件的最佳方式。如果文件较大,您可能希望使用文件流而不是内存流。如果您的应用程序仅在更新过程中使用网络,则使用Indy将增加.exe的大小。这基本上不是我八年前的答案的副本吗?:)我不这么认为。