6


2

私はSystem.Windows.Forms.WebBrowserを使ってC#で書かれたWebCrawlerに取り組んできました。 Webサイトからファイルをダウンロードしてローカルコンピュータに保存しようとしています。 さらに重要なことに、私はこれを完全に自動化したいと思います。 ファイルのダウンロードは、「このファイルを開くか保存しますか?」というダイアログが表示されたダウンロードを促すjavascript関数を呼び出すボタンをクリックすることで開始できます。 私は絶対に手動で「名前を付けて保存」をクリックしてファイル名を入力したくはありません。

HttpWebRequestとWebClientのダウンロード機能は知っていますが、ダウンロードはJavaScriptで開始されるので、ファイルのURLはわかります。 Fyi、javascriptは値をいくつか変更してフォームを送信するdoPostBack関数です。

私は、WebBrowserからダイアログとして保存することに集中して、そこから自動化してもあまり成功しませんでした。 http要求にヘッダーを追加して保存または開くのではなく、ダウンロードを強制的に保存する方法はありますが、ダウンロード先のファイルパスを指定する方法がわかりません。

4 Answer


5


ダウンロードダイアログが表示されないようにするべきです。 これを行う方法があります。

  • Javascriptコードにより、WebBrowserコントロールは特定のURLに移動します(ダウンロードダイアログが表示される原因となります)。

  • WebBrowserコントロールが実際にこのUrlに移動しないようにするには、イベントハンドラをNavigatingイベントに添付します。

  • Navigatingイベントで、これが実際に停止したいナビゲーションアクションであるかどうかを分析する必要があります(これはダウンロードURLです。おそらくファイル拡張子を確認してください、認識可能な形式が必要です)。 そのためにはWebBrowserNavigatingEventArgs.Urlを使用してください。

  • これが正しいURLの場合は、WebBrowserNavigatingEventArgs.Cancelプロパティを設定してナビゲーションを停止します。

  • HttpWebRequestクラスまたはWebClientクラスを使用して自分でダウンロードを続けます。

イベントの詳細については、このページをご覧ください。http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.navigating.aspx


4


同様の解決策がhttp://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/d338a2c8-96df-4cb0-b8be-c5fbdd7c9202/?prof=requiredで入手できます。

ダウンロードファイル名を含む直接のURLがあればこれは完全に動作します。

しかし、いつかあるURLは動的にファイルを生成します。 そのためURLにはファイル名がありませんが、そのURLを要求した後にWebサイトを動的に作成してから開く/保存ダイアログが表示されます。

例えば、あるリンクはその場でpdfファイルを生成します。

このような種類のURLを処理する方法


1


*動的に生成されたpdf URLをダウンロードするためにこれを使用しました


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()
        .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(http://www.codeproject.com/Tips/659004/Download-of-file-with-から入手可能)で提供されている素晴らしい記事にあります。開く保存ダイアログボックス[ここ])、

[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;
}