2012-11-30 64 views
1

注意: 此代碼在Delphi XE2中。Delphi - 使用Wininet下載文件?

我試圖下載文件而不使用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字節。

+0

你要當ReadNext <1024 BTW一個更好的名字停止該變量是BytesRead。 – jachguate

+0

沒有改變。我甚至在InternetReadFile顯示ReadNext變量或「BytesRead」後顯示一個MessageBox,它顯示0. –

+0

請注意,WinInet已過時!!!!!!!!!!您可能想要使用WinHTTP:http://blog.synopse.info/post/2011/07/04/WinINet-vs-WinHTTP – Ampere

回答

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的結果,並拋出一個異常,如果是假的,或者寫入的字節數是從許多不同的讀取的字節數。
  • 更改了變量名稱。
  • 命名常量
  • [後編輯]功能定位結果檢查
  • [後編輯]使用try/finally塊

編輯感謝TLama資源泄漏保護提高認識有關最後兩個點。

+0

您能解釋一下如何在delphi 7應用程序中執行相同的代碼嗎?在delphi 7這個代碼編譯,但沒有正確下載文件。它似乎一遍又一遍地添加同一行「字節序列」... –

+0

實際上,我編輯所有「PWideChar」到「PChar」,也嘗試過「PAnsiChar」 –

+0

Josh,你必須匹配Windows API。在2009年德爾福,它是Ansi,所以你必須使用PChar或PAnsiChar。在德爾福2009+是unicode,所以你使用PWideChar或PChar,因爲它們是等價的。最安全的做法是總是使用PChar做演員。 – jachguate

-1

這首先是錯誤的。

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

需求是

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

而且缺少)在這裏....

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

不要得到它,我寫這個代碼2錯誤,我得到-1 :))))好noob – mel