使用没有url的WebBrowser自动下载文件

时间:2009-07-17 20:09:29

标签: c# winforms download browser web-crawler

我一直在使用System.Windows.Forms.WebBrowser编写用C#编写的WebCrawler。我试图从网站上下载文件并将其保存在本地计算机上。更重要的是,我希望这是完全自动化的。可以通过单击调用javascript函数的按钮来启动文件下载,该函数会激活下载,显示“是否要打开或保存此文件?”对话框。我绝对不想手动点击“另存为”,并输入文件名。

我知道HttpWebRequest和WebClient的下载功能,但由于下载是用javascript启动的,我现在知道该文件的URL。 Fyi,javascript是一个doPostBack函数,可以更改某些值并提交表单。

我已经尝试将重点放在WebBrowser的“保存为对话框”上,以便从那里自动化它,但没有取得多大成功。我知道有一种方法可以强制下载保存,而不是通过向http请求添加标头来保存或打开,但我不知道如何指定要下载的文件路径。

4 个答案:

答案 0 :(得分:5)

我认为你应该阻止下载对话框显示。这可能是一种方法:

  • Javascript代码会导致您的WebBrowser控件导航到特定的Url(导致下载对话框出现的原因)

  • 要阻止WebBrowser控件实际导航到此Url,请将事件处理程序附加到导航事件。

  • 在您的导航事件中,您必须分析这是否是您想要停止的实际导航操作(这是下载网址,也许是检查文件扩展名,必须有可识别的格式)。使用WebBrowserNavigatingEventArgs.Url执行此操作。

  • 如果这是正确的Url,请通过设置WebBrowserNavigatingEventArgs.Cancel属性来停止导航。

  • 使用HttpWebRequest或WebClient类继续下载

有关此次活动的更多信息,请查看此页面:
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.navigating.aspx

答案 1 :(得分:4)

类似的解决方案可在 http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/d338a2c8-96df-4cb0-b8be-c5fbdd7c9202/?prof=required

如果有包含下载文件名的直接URL,这项工作就完美了。

但有时某些URL会动态生成文件。所以URL没有文件名,但在请求该URL后,某个网站动态创建文件,然后打开/保存对话框。

例如某些链接即时生成pdf文件。

如何处理此类网址?

答案 2 :(得分:1)

看看http://www.codeproject.com/Tips/659004/Download-of-file-with-open-save-dialog-box

上的Erika Chinchio文章

我已成功使用它下载动态生成的pdf网址。

答案 3 :(得分:1)

假设使用System.Windows.Forms.WebBrowswer访问具有您要下载的受保护链接的受保护页面:

此代码使用Web浏览器检索您要下载的实际链接。 此代码需要针对您的具体操作进行更改。重要的部分是将在下面使用的字段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

        }
    }
}

上面的代码依赖于Erika Chinchio的GetGlobalCookies方法,可以在@Pedro Leonardo(可用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;
}