Delphi - 使用Wininet下载文件?

时间:2012-11-30 03:54:41

标签: delphi download wininet

注意: 此代码在Delphi XE2中。

我试图在不使用UrlMon.dll的情况下下载文件。

我想只使用wininet。这是我到目前为止所提出的:

uses Windows, Wininet;

procedure DownloadFile(URL:String;Path:String);
Var
  InetHandle:Pointer;
  URLHandle:Pointer;
  FileHandle:Cardinal;
  ReadNext:Cardinal;
  DownloadBuffer:Pointer;
  BytesWritten:Cardinal;
begin
  InetHandle := InternetOpen(PWideChar(URL),0,0,0,0);
  URLHandle := InternetOpenUrl(InetHandle,PWideChar(URL),0,0,0,0);
  FileHandle := CreateFile(PWideChar(Path),GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,0);
  Repeat
    InternetReadFile(URLHandle,DownloadBuffer,1024,ReadNext);
    WriteFile(FileHandle,DownloadBuffer,ReadNext,BytesWritten,0);
  Until ReadNext = 0;
  CloseHandle(FileHandle);
  InternetCloseHandle(URLHandle);
  InternetCloseHandle(InetHandle);
end;

我认为问题出在我的循环和“ReadNext”上。执行此代码时,它会在正确的路径中创建文件,但代码完成,文件为0字节。

2 个答案:

答案 0 :(得分:1)

我改善了你的日常工作,它为我做了工作:

procedure DownloadFile(URL: string; Path: string);
const
  BLOCK_SIZE = 1024;
var
  InetHandle: Pointer;
  URLHandle: Pointer;
  FileHandle: Cardinal;
  BytesRead: Cardinal;
  DownloadBuffer: Pointer;
  Buffer: array [1 .. BLOCK_SIZE] of byte;
  BytesWritten: Cardinal;
begin
  InetHandle := InternetOpen(PWideChar(URL), 0, 0, 0, 0);
  if not Assigned(InetHandle) then RaiseLastOSError;
  try
    URLHandle := InternetOpenUrl(InetHandle, PWideChar(URL), 0, 0, 0, 0);
    if not Assigned(URLHandle) then RaiseLastOSError;
    try
      FileHandle := CreateFile(PWideChar(Path), GENERIC_WRITE, FILE_SHARE_WRITE, 0,
        CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
      if FileHandle = INVALID_HANDLE_VALUE then RaiseLastOSError;
      try
        DownloadBuffer := @Buffer;
        repeat
          if (not InternetReadFile(URLHandle, DownloadBuffer, BLOCK_SIZE, BytesRead) 
             or (not WriteFile(FileHandle, DownloadBuffer^, BytesRead, BytesWritten, 0)) then
            RaiseLastOSError;
        until BytesRead = 0;
      finally
        CloseHandle(FileHandle);
      end;
    finally
      InternetCloseHandle(URLHandle);
    end;
  finally
    InternetCloseHandle(InetHandle);
  end;
end;

例如电话:

  DownloadFile
    ('https://dl.dropbox.com/u/21226165/XE3StylesDemo/StylesDemoSrcXE2.7z',
    '.\StylesDemoXE2.7z');

像魅力一样。

我所做的改变是:

  • 提供缓冲区
  • 检查对WriteFile的调用结果,如果为false,或者写入的字节数与读取的字节数不同,则引发异常。
  • 更改了变量名称。
  • 命名常数
  • [编辑后]正确的功能结果检查
  • [编辑后]使用try / finally块进行资源泄漏保护

编辑感谢TLama提高对最后两点的了解。

答案 1 :(得分:-1)

这首先是错误的。

InetHandle := InternetOpen(PChar(URL), 0, 0, 0, 0);

需要

InetHandle := InternetOpen(PChar(USERANGENT), 0, 0, 0, 0);

在这里错过了a)....

(not InternetReadFile(URLHandle, DownloadBuffer, BLOCK_SIZE, BytesRead) ")"