Delphi - 需要 XE2 代码到 Delphi7。使用wininet下载文件

Posted

技术标签:

【中文标题】Delphi - 需要 XE2 代码到 Delphi7。使用wininet下载文件【英文标题】:Delphi - XE2 code to Delphi7 needed. Using wininet to download a file 【发布时间】:2012-11-30 06:24:24 【问题描述】:

注意:我只想使用wininet,而不是urlmon-urldownloadtofile。

嗯,我有以下代码在 XE2 中完美地下载文件:

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);
  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);
  DownloadBuffer := @Buffer;
  repeat
    InternetReadFile(URLHandle, DownloadBuffer, BLOCK_SIZE, BytesRead);
    if not WriteFile(FileHandle, DownloadBuffer, BytesRead, BytesWritten, 0) or
  (BytesWritten <> BytesRead) then
      RaiseLastOSError;
  until BytesRead < BLOCK_SIZE;
  CloseHandle(FileHandle);
  InternetCloseHandle(URLHandle);
  InternetCloseHandle(InetHandle);
end;

以上代码的学分转到jachguate。他编辑了我的代码以更正它,为此我感谢他。

现在,这段代码只能在 Delphi XE2 下正常工作。我尝试在 Delphi 7 下使用它,但它无法正常工作。它似乎在文件中一遍又一遍地存储相同的“行”或“字节序列”。

以下是我尝试在 Delphi 7 中使用的上述代码的两种改型 - 两者都不能正常工作。

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(PChar(URL), 0, 0, 0, 0);
  URLHandle := InternetOpenUrl(InetHandle, PChar(URL), 0, 0, 0, 0);
  FileHandle := CreateFile(PChar(Path), GENERIC_WRITE, FILE_SHARE_WRITE, 0,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
  DownloadBuffer := @Buffer;
  repeat
    InternetReadFile(URLHandle, DownloadBuffer, BLOCK_SIZE, BytesRead);
    if not WriteFile(FileHandle, DownloadBuffer, BytesRead, BytesWritten, 0) or
  (BytesWritten <> BytesRead) then
      RaiseLastOSError;
  until BytesRead < BLOCK_SIZE;
  CloseHandle(FileHandle);
  InternetCloseHandle(URLHandle);
  InternetCloseHandle(InetHandle);
end;

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(PAnsiChar(URL), 0, 0, 0, 0);
  URLHandle := InternetOpenUrl(InetHandle, PAnsiChar(URL), 0, 0, 0, 0);
  FileHandle := CreateFile(PAnsiChar(Path), GENERIC_WRITE, FILE_SHARE_WRITE, 0,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
  DownloadBuffer := @Buffer;
  repeat
    InternetReadFile(URLHandle, DownloadBuffer, BLOCK_SIZE, BytesRead);
    if not WriteFile(FileHandle, DownloadBuffer, BytesRead, BytesWritten, 0) or
  (BytesWritten <> BytesRead) then
      RaiseLastOSError;
  until BytesRead < BLOCK_SIZE;
  CloseHandle(FileHandle);
  InternetCloseHandle(URLHandle);
  InternetCloseHandle(InetHandle);
end;

唯一编辑的是数据类型转换。示例一使用了“PChar”,示例二使用了“PAnsiChar”。

【问题讨论】:

【参考方案1】:

您在文件中得到了垃圾,因为您需要使用 ^ 字符取消引用指针 DownloadBuffer,因此要修复您的方法只需替换此代码

WriteFile(FileHandle, DownloadBuffer, BytesRead, BytesWritten, 0)

通过这个

WriteFile(FileHandle, DownloadBuffer^, BytesRead, BytesWritten, 0)

顺便说一句,记得在函数中添加 try..finally 块,以确保在发生异常时释放句柄。

【讨论】:

以上是关于Delphi - 需要 XE2 代码到 Delphi7。使用wininet下载文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Delphi XE2 中将菜单项添加到 Mac OS Finder

在 Delphi XE2 中使用泛型和前向声明时的编译器错误

如何使用Delphi XE2覆盖WSDL中的服务名称?

如何改变delphi xe2编程环境下所显示的源代码的字体大小

delphi xe2实现.net中的wcf并支持回调

如何从 Delphi XE2 加速文字自动化