2009-07-17 6 views
5

J'ai travaillé sur un WebCrawler écrit en C# à l'aide de System.Windows.Forms.WebBrowser. J'essaie de télécharger un fichier sur un site Web et de l'enregistrer sur une machine locale. Plus important encore, j'aimerais que cela soit entièrement automatisé. Le téléchargement du fichier peut être démarré en cliquant sur un bouton qui appelle une fonction javascript qui déclenche le téléchargement en affichant une boîte de dialogue "Voulez-vous ouvrir ou enregistrer ce fichier?". Je ne veux définitivement pas cliquer manuellement sur "Enregistrer sous" et saisir le nom du fichier.Téléchargement automatique de fichiers avec WebBrowser sans URL

Je suis conscient des fonctions de téléchargement de HttpWebRequest et de WebClient, mais depuis que le téléchargement est démarré avec un javascript, je connais maintenant l'URL du fichier. Fyi, le javascript est une fonction doPostBack qui modifie certaines valeurs et soumet un formulaire.

J'ai essayé de me concentrer sur la boîte de dialogue Enregistrer sous de WebBrowser pour l'automatiser sans grand succès. Je sais qu'il existe un moyen de forcer le téléchargement à sauvegarder au lieu de demander d'enregistrer ou d'ouvrir en ajoutant un en-tête à la requête http, mais je ne sais pas comment spécifier le chemin du fichier à télécharger.

+0

Avez-vous une solution à votre dernière problème, comment télécharger le fichier quand il est généré à la volée et vous ne pouvez pas déterminer qu'il s'agit d'un téléchargement de fichier à partir de l'URL? –

Répondre

5

Je pense que vous devriez éviter d'afficher la boîte de dialogue de téléchargement. Voici peut-être une façon de le faire:

  • Le code Javascript provoque le contrôle de votre navigateur Web pour accéder à une URL spécifique (ce qui cause la boîte de dialogue de téléchargement apparaisse)

  • Pour éviter le contrôle WebBrowser de En fait, naviguez jusqu'à cette URL et attachez un gestionnaire d'événement à l'événement Navigation. Dans votre événement de navigation, vous devez analyser si c'est l'action de navigation que vous souhaitez arrêter (est-ce l'url de téléchargement, peut-être vérifier une extension de fichier, il doit y avoir un format reconnaissable) . Utilisez le WebBrowserNavigatingEventArgs.Url pour le faire.

  • Si cette URL est la bonne, arrêtez la navigation en définissant la propriété WebBrowserNavigatingEventArgs.Cancel.

  • Continuer le téléchargement vous avec les HttpWebRequest ou les classes WebClient

Jetez un oeil sur cette page pour plus d'informations sur l'événement:
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.navigating.aspx

+1

J'ai déjà essayé d'obtenir l'url en utilisant un HttpDebugger pour regarder la requête http et les réponses. L'URL est exactement la même, l'une étant une requête GET, l'autre étant une requête POST. J'ai aussi essayé votre suggestion sans avoir de chance. – Sharath

+0

Vous pouvez utiliser le contrôle WebBrowser pour arriver à la fin, juste avant que le formulaire ne soit soumis, puis extraire la destination POST du formulaire en utilisant DOM (obtenir une référence au corps du document HTML et à partir de là faire votre chemin vers la forme). – Zyphrax

3

Une solution similaire est disponible à http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/d338a2c8-96df-4cb0-b8be-c5fbdd7c9202/?prof=required

Ceci fonctionne parfaitement s'il y a une URL directe incluant le téléchargement du nom de fichier.

Mais parfois certaines URL génèrent des fichiers dynamiquement. Donc, l'URL n'a pas de nom de fichier, mais après avoir demandé à cette URL, un site web crée un fichier dynamiquement, puis une boîte de dialogue d'ouverture/de sauvegarde apparaît. Par exemple, un lien génère un fichier pdf à la volée.

Comment gérer un tel type d'URL?

1

Jetez un oeil à l'article Erika Chinchio sur http://www.codeproject.com/Tips/659004/Download-of-file-with-open-save-dialog-box

Je l'ai utilisé avec succès pour le téléchargement générés dynamiquement urls pdf.

+2

Bien que cela puisse théoriquement répondre à la question, [il serait préférable] (// meta.stackoverflow.com/q/8259) d'inclure les parties essentielles de la réponse ici, et de fournir le lien pour référence. –

1

En supposant que le System.Windows.Forms.WebBrowswer a été utilisé pour accéder à une page protégée par un lien protégé que vous voulez télécharger:

Ce code récupère le lien réel que vous souhaitez télécharger en utilisant le web navigateur. Ce code devra être modifié pour votre action spécifique. La partie importante est un champ documentLinkUrl qui sera utilisé ci-dessous.

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); 

Maintenant que la page a été protégée par le navigué navigateur Web et le lien de téléchargement a été acquis, ce code télécharge le lien.

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 

     } 
    } 
} 

Le code ci-dessus repose sur la méthode GetGlobalCookies de Erika Chinchio qui se trouve dans l'excellent article fourni par @Pedro Leonardo (disponible 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; 
} 
Questions connexes