2009-07-17 72 views
5

我一直在使用System.Windows.Forms.WebBrowser編寫C#編寫的WebCrawler。我正試圖從網站上下載文件並將其保存在本地計算機上。更重要的是,我希望這是完全自動化的。點擊一個調用JavaScript函數的按鈕即可啓動文件下載,該函數觸發下載並顯示「您要打開還是保存此文件?」對話框。我絕對不想手動點擊「另存爲」,然後輸入文件名。使用WebBrowser無url的自動化文檔下載

我知道HttpWebRequest和WebClient的下載功能,但由於下載是用javascript開始的,我現在知道該文件的URL。 Fyi,javascript是一個doPostBack函數,用於更改一些值並提交表單。

我試過把重點放在保存爲WebBrowser的對話框上,以便在那裏沒有太大的成功自動化它。我知道有一種方法可以強制下載來保存,而不是通過向http請求添加頭來保存或打開,但我不知道如何指定要下載的文件路徑。

+0

你有一個解決方案,你最後問題,如何在動態生成文件時下載文件,並且您無法確定它是否是從網址下載的文件? – 2011-05-06 07:07:54

回答

5

我認爲你應該防止下載對話框顯示出來。這裏可能是一個辦法做到這一點:

  • 的JavaScript代碼導致你的瀏覽器控件導航到一個特定的URL(什麼會導致出現下載對話框)

  • 爲了防止WebBrowser控件從實際導航到此Url,將事件處理程序附加到Navigating事件。

  • 在您的導航事件中,如果這是您想要停止的實際導航操作(這是一個下載URL,可能檢查文件擴展名,必須有可識別的格式) 。使用WebBrowserNavigatingEventArgs.Url來執行此操作。

  • 如果這是正確的Url,請通過設置WebBrowserNavigatingEventArgs.Cancel屬性來停止導航。

  • 自己繼續下載用的HttpWebRequest或WebClient的類

看一看這個網頁,瞭解事件的詳細信息:
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.navigating.aspx

+1

我已經嘗試過讓使用HttpDebugger看HTTP請求和響應的URL。 url完全一樣,一個是GET請求,另一個是POST請求。 我也試過你的建議沒有運氣。 – Sharath 2009-07-17 20:40:53

+0

你可能想使用WebBrowser控件才能到盡頭,表單將提交之前,然後提取使用DOM形式的POST目的地(獲取到HTML文檔正文的引用,並從那裏用自己的方式表格)。 – Zyphrax 2009-07-18 10:52:41

1

假設System.Windows.Forms.WebBrowswer使用與您想要下載受保護的鏈接訪問受保護的頁面:

此代碼檢索實際的鏈接你想利用網絡來下載瀏覽器。 此代碼將需要爲您的特定操作進行更改。重要的部分是這個字段documentLinkUrl,將在下面使用。

var documentLinkUrl = default(Uri); 
browser.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) => 
{ 
    var aspForm = browser.Document.Forms[0]; 
    var downloadLink = browser.Document.ActiveElement 
     .GetElementsByTagName("a").OfType<HtmlElement>() 
     .Where(atag => 
      atag.GetAttribute("href").Contains("DownloadAttachment.aspx")) 
     .First(); 

    var documentLinkString = downloadLink.GetAttribute("href"); 
    documentLinkUrl = new Uri(documentLinkString); 
} 
browser.Navigate(yourProtectedPage); 

現在,受保護的頁面已經被Web瀏覽器導航到和下載鏈接已被收購,此代碼下載鏈接。

private static async Task DownloadLinkAsync(Uri documentLinkUrl) 
{ 
    var cookieString = GetGlobalCookies(documentLinkUrl.AbsoluteUri); 
    var cookieContainer = new CookieContainer(); 
    using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer }) 
    using (var client = new HttpClient(handler) { BaseAddress = documentLinkUrl }) 
    { 
     cookieContainer.SetCookies(this.documentLinkUrl, cookieString); 
     var response = await client.GetAsync(documentLinkUrl); 
     if (response.IsSuccessStatusCode) 
     { 
      var responseAsString = await response.Content.ReadAsStreamAsync(); 
      // Response can be saved from Stream 

     } 
    } 
} 

上面的代碼依賴於從埃裏卡Chinchio的GetGlobalCookies方法可以通過@Pedro萊昂納多(可here)提供了出色的文章中找到,

[System.Runtime.InteropServices.DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] 
static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, 
    System.Text.StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved); 

const int INTERNET_COOKIE_HTTPONLY = 0x00002000; 

private string GetGlobalCookies(string uri) 
{ 
    uint uiDataSize = 2048; 
    var sbCookieData = new System.Text.StringBuilder((int)uiDataSize); 
    if (InternetGetCookieEx(uri, null, sbCookieData, ref uiDataSize, 
      INTERNET_COOKIE_HTTPONLY, IntPtr.Zero) 
     && 
     sbCookieData.Length > 0) 
    { 
     return sbCookieData.ToString().Replace(";", ","); 
    } 
    return null; 
}