Delphi文件下载组件

4

我需要一个用于Delphi的文件下载组件。你能帮助我吗?


1
除了能够下载文件之外,这个组件还会做些什么?为什么它应该是一个组件而不是一个库,或者只是一个独立的函数呢? - Rob Kennedy
我没有足够的时间去学习它,所以我需要一个已准备好并且运作良好的组件。 - Kermia
2
你没有足够的时间弄清楚你需要什么?那你怎么知道是否找到了它呢? - Rob Kennedy
2个回答

12

使用高级别的URLDownloadToFile函数:


uses UrlMon;

...

URLDownloadToFile(nil, 'http://www.rejbrand.se/', 'C:\Users\Andreas Rejbrand\Desktop\index.html', 0, nil);

或者,你可以非常容易地使用WinInet函数编写自己的下载器功能,类似于:

uses WinInet;

...

hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
try
  hURL := InternetOpenUrl(hInet, PChar('http://' + Server + Resource), nil, 0, 0, 0);
  try
    repeat
      InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);

      ...

在SO上有很多样例代码。请使用上面的搜索框。

更新

我写了一个小示例。你可能想要在单独的线程中执行此代码,并让它每隔10KB左右回传一次,这样你就可以向用户提供一些进度条等信息。

function DownloadFile(const UserAgent, URL, FileName: string): boolean;
const
  BUF_SIZE = 4096;
var
  hInet, hURL: HINTERNET;
  f: file;
  buf: PByte;
  amtc: cardinal;
  amti: integer;
begin
  result := false;
  hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  try
    hURL := InternetOpenUrl(hInet, PChar(URL), nil, 0, 0, 0);
    try
      GetMem(buf, BUF_SIZE);
      try
        FileMode := fmOpenWrite;
        AssignFile(f, FileName);
        try
          Rewrite(f, 1);
          repeat
            InternetReadFile(hURL, buf, BUF_SIZE, amtc);
            BlockWrite(f, buf^, amtc, amti);
          until amtc = 0;
          result := true;
        finally
          CloseFile(f);
        end;
      finally
        FreeMem(buf);
      end;
    finally
      InternetCloseHandle(hURL);
    end;
  finally
    InternetCloseHandle(hInet);
  end;
end;

7
我不明白人们对TStream有什么反感……例如FileMode:= fmOpenWrite不是线程安全的,因为它会设置一个全局变量。 - user160694
5
@Idsandon:天哪,我讨厌人们对传统方法提出有效的论据... :)(说实话,我以前从未考虑过这个问题,但它确实很有道理。) 我讨厌当人们对古老的方法提出有效的论据时。 :) (坦率地说,我以前从未考虑过这个问题,但它确实是合理的。) - Andreas Rejbrand
3
@pani,我不相信那个。就算在某个时间点上有几天是真的。 - Cosmin Prund
1
@pani:仅仅因为静态加载了一些API就将某个东西判定为潜在病毒是一个很大的错误;我不相信杀毒软件公司会如此愚蠢,除非他们想要倒闭。哪个杀毒软件在3年前认为使用这个API可能存在问题,而今天仍然如此呢? - Cosmin Prund
1
@Pani,请提供一些证明。要么编译此代码并发布您的杀毒软件程序报告,要么发布其他人进行类似实验的链接。 - Rob Kennedy
显示剩余6条评论

7

你也可以使用Indy来制作:

procedure DownloadHTTP(const AUrl : string; DestStream: TStream);
begin
  with TIdHTTP.Create(Application) do
  try
      try
        Get(AUrl,DestStream);
      except
        On e : Exception do
          MessageDlg(Format('Erreur : %s',[e.Message]), mtInformation, [mbOK], 0);
      end;
  finally
      Free;
  end;
end;

如果您想要快速下载,您也可以使用Clever Internet Suite

这种方式太慢了,而且我无法更改块值! - Kermia
1
太慢了?怎么办?“块值”是什么?你在问题中从未提到过它。 - Rob Kennedy
我从未觉得Indy慢,但如果您需要更快的组件,我可以为您添加一个新链接(它似乎更快)。 - Hugues Van Landeghem

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