1

注:私は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に送られます。彼は私のコードを編集して修正しました、そして私は彼に感謝します。

現在、このコードはDelphiXE2でのみ正しく機能します。Delphi 7で使用しようとしましたが、正しく機能しません。同じ「行」または「バイトシーケンス」をファイルに数回何度も保存しているようです。

以下は、私がDelphi 7で使用しようとした上記のコードの2つの改革であり、どちらも正しく機能しませんでした。

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;

編集されたのはデータ型の変換だけでした。例1の「PChar」が使用され、例2の「PAnsiChar」が使用されました。

4

1 に答える 1

5

charDownloadBufferを使用し てポインタを逆参照する必要があるため、ファイルにガベージが発生しているため、メソッドを修正するには、このコードを置き換えるだけです。^

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

これで

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

ところで、例外が発生したときにハンドルを確実に解放するために、関数にtry..finallyブロックを追加することを忘れないでください。

于 2012-11-30T13:52:41.413 に答える