2009-07-17 5 views
5

Ho lavorato a un WebCrawler scritto in C# utilizzando System.Windows.Forms.WebBrowser. Sto cercando di scaricare un file da un sito Web e salvarlo su un computer locale. Ancora più importante, mi piacerebbe che fosse completamente automatizzato. Il download del file può essere avviato facendo clic su un pulsante che richiama una funzione javascript che attiva il download visualizzando una finestra di dialogo "Vuoi aprire o salvare questo file?". Non voglio assolutamente fare clic manualmente su "Salva come" e digitando il nome del file.Caricamento file automatico utilizzando WebBrowser senza url

Sono a conoscenza delle funzioni di download di HttpWebRequest e WebClient, ma poiché il download è iniziato con un javascript, ora conosco l'URL del file. Fyi, il javascript è una funzione doPostBack che modifica alcuni valori e invia un modulo.

Ho provato a mettere a fuoco il salvataggio come finestra di dialogo da WebBrowser per automatizzarlo da lì senza molto successo. So che c'è un modo per forzare il download da salvare invece di chiedere di salvare o aprire aggiungendo un'intestazione alla richiesta http, ma non so come specificare il percorso file da scaricare.

+0

Avete una soluzione per il vostro ultimo problema, come scaricare il file quando viene generato al volo e non è possibile determinare che si tratta di un download di file dall'URL? –

risposta

5

Penso che dovresti impedire la visualizzazione della finestra di download. Qui potrebbe essere un modo per farlo:

  • Il codice JavaScript fa sì che il controllo WebBrowser per passare a un URL specifico (quello che sarebbe far apparire la finestra di download)

  • Per evitare che il controllo WebBrowser da Effettivamente Navigando verso questo Url, collega un gestore di eventi all'evento Navigating.

  • Nel vostro evento Navigating che avrebbe dovuto analizzare se questa è l'azione di navigazione effettiva che ci si vuole fermare (è questo l'URL per il download, forse controllare per un'estensione di file, ci deve essere un formato riconoscibile) . Utilizzare WebBrowserNavigatingEventArgs.Url per farlo.

  • Se questo è l'URL corretto, interrompere la navigazione impostando la proprietà WebBrowserNavigatingEventArgs.Cancel.

  • Continuare il download da soli con le HttpWebRequest o WebClient classi

Date un'occhiata a questa pagina per maggiori informazioni sull'evento:
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.navigating.aspx

+1

Ho già provato a ottenere l'url utilizzando un HttpDebugger per esaminare la richiesta e le risposte http. L'url è esattamente lo stesso, essendo una richiesta GET, l'altra è una richiesta POST. Ho anche appena provato il tuo suggerimento senza fortuna. – Sharath

+0

Potrebbe essere utile utilizzare il controllo WebBrowser per arrivare alla fine, prima che il modulo venga inviato e quindi estrarre la destinazione POST del modulo utilizzando DOM (ottenere un riferimento al corpo del documento HTML e da lì fare il proprio il modulo). – Zyphrax

3

Una soluzione simile è disponibile presso http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/d338a2c8-96df-4cb0-b8be-c5fbdd7c9202/?prof=required

Questo funziona perfettamente se vi è un URL diretto che include il download del nome del file.

Ma qualche volta qualche URL genera file dinamicamente. Quindi l'URL non ha il nome del file ma dopo aver richiesto quell'URL alcuni siti web creano il file dinamicamente e quindi viene visualizzata la finestra di dialogo di apertura/salvataggio.

per esempio alcuni link generano file pdf al volo.

Come gestire questo tipo di URL?

1

Date un'occhiata a un articolo Erika Chinchio su http://www.codeproject.com/Tips/659004/Download-of-file-with-open-save-dialog-box

ho usato con successo per il download gli URL PDF generati in modo dinamico.

+2

Sebbene ciò possa teoricamente rispondere alla domanda, [sarebbe preferibile] (// meta.stackoverflow.com/q/8259) includere qui le parti essenziali della risposta e fornire il link per riferimento. –

1

Supponendo che lo System.Windows.Forms.WebBrowswer è stato utilizzato per accedere a una pagina protetta con un link protetto che si desidera scaricare:

Questo codice recupera il collegamento reale che si desidera scaricare utilizzando il web browser. Questo codice dovrà essere modificato per l'azione specifica. La parte importante è questo un campo documentLinkUrl che verrà utilizzato di seguito.

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

Ora che la pagina è stata protetta navigato per il browser web e il link per il download è stato acquisito, questo codice di download link.

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 

     } 
    } 
} 

Il codice di cui sopra si basa sul metodo GetGlobalCookies da Erika Chinchio che si trova nella eccellente articolo fornito da @Pedro Leonardo (disponibile 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; 
}