Faça o download do arquivo e salve-o automaticamente na pasta

Eu estou tentando fazer uma interface do usuário para baixar arquivos do meu site. O site tem arquivos zip e estes precisam ser baixados para o diretório typescript pelo usuário. No entanto, não consigo fazer o download do arquivo, ele apenas abre a partir de uma pasta temporária.

Código:

private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) { e.Cancel = true; string filepath = null; filepath = textBox1.Text; WebClient client = new WebClient(); client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted); client.DownloadFileAsync(e.Url, filepath); } 

Código fonte completo: http://en.paidpaste.com/LqEmiQ

Por que não apenas ignorar completamente as partes de manipulação de arquivos do WebClient. Talvez algo semelhante a isto:

  private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) { e.Cancel = true; WebClient client = new WebClient(); client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted); client.DownloadDataAsync(e.Url); } void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) { string filepath = textBox1.Text; File.WriteAllBytes(filepath, e.Result); MessageBox.Show("File downloaded"); } 

Meu programa faz exatamente o que você está depois, sem prompts ou qualquer coisa, por favor, veja o código a seguir.

Este código irá criar todos os diretórios necessários se eles ainda não existirem:

 Directory.CreateDirectory(C:\dir\dira\dirb); // This code will create all of these directories 

Este código irá baixar o arquivo fornecido para o diretório fornecido (depois que ele foi criado pelo snippet anterior:

 private void install() { WebClient webClient = new WebClient(); // Creates a webclient webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed); // Uses the Event Handler to check whether the download is complete webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); // Uses the Event Handler to check for progress made webClient.DownloadFileAsync(new Uri("http://www.com/newfile.zip"), @"C\newfile.zip"); // Defines the URL and destination directory for the downloaded file } 

Portanto, usando esses dois códigos, você pode criar todos os diretórios e informar ao downloader (que não solicita o download do arquivo para esse local.

Se você não quiser usar “WebClient” ou / e precisar usar o System.Windows.Forms.WebBrowser, por exemplo, porque você quer simular um login primeiro, você pode usar este WebBrowser estendido que engancha o método “URLDownloadToFile” do Windows URLMON Lib e usa o Contexto do WebBrowser

Infos: http://www.pinvoke.net/default.aspx/urlmon/URLDownloadToFile%20.html

 using System; using System.IO; using System.Runtime.InteropServices; using System.Windows.Forms; namespace dataCoreLib.Net.Webpage { public class WebBrowserWithDownloadAbility : WebBrowser { ///  /// The URLMON library contains this function, URLDownloadToFile, which is a way /// to download files without user prompts. The ExecWB( _SAVEAS ) function always /// prompts the user, even if _DONTPROMPTUSER parameter is specified, for "internet /// security reasons". This function gets around those reasons. ///  /// Pointer to caller object (AX). /// String of the URL. /// String of the destination filename/path. /// [reserved]. /// A callback function to monitor progress or abort. /// 0 for okay. /// source: http://www.pinvoke.net/default.aspx/urlmon/URLDownloadToFile%20.html [DllImport("urlmon.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern Int32 URLDownloadToFile( [MarshalAs(UnmanagedType.IUnknown)] object callerPointer, [MarshalAs(UnmanagedType.LPWStr)] string url, [MarshalAs(UnmanagedType.LPWStr)] string filePathWithName, Int32 reserved, IntPtr callBack); ///  /// Download a file from the webpage and save it to the destination without promting the user ///  /// the url with the file /// the absolut full path with the filename as destination ///  public FileInfo DownloadFile(string url, string destinationFullPathWithName) { URLDownloadToFile(null, url, destinationFullPathWithName, 0, IntPtr.Zero); return new FileInfo(destinationFullPathWithName); } } } 

Bem, sua solução quase funciona. Existem algumas coisas para levar em conta para simplificar:

  • Cancele a navegação padrão apenas para URLs específicos que você sabe que um download ocorrerá ou o usuário não conseguirá navegar em nenhum lugar. Isso significa que você não precisa alterar os URLs de download de seu website.

  • DownloadFileAsync não sabe o nome relatado pelo servidor no header Content-Disposition portanto, você precisa especificar um ou calcular um do URL original, se isso for possível. Você não pode simplesmente especificar a pasta e esperar que o nome do arquivo seja recuperado automaticamente.

  • Você tem que lidar com erros de servidor de DownloadCompleted retorno de chamada DownloadCompleted porque o controle do navegador da web não vai fazer isso por você mais.

Exemplo de código que será transferido para o diretório especificado em textBox1 , mas com um nome de arquivo random e sem qualquer tratamento de erro adicional:

 private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) { /* change this to match your URL. For example, if the URL always is something like "getfile.php?file=xxx", try e.Url.ToString().Contains("getfile.php?") */ if (e.Url.ToString().EndsWith(".zip")) { e.Cancel = true; string filePath = Path.Combine(textBox1.Text, Path.GetRandomFileName()); var client = new WebClient(); client.DownloadFileCompleted += client_DownloadFileCompleted; client.DownloadFileAsync(e.Url, filePath); } } private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { MessageBox.Show("File downloaded"); } 

Essa solução deve funcionar, mas pode ser quebrada com muita facilidade. Tente considerar algum serviço da Web listando os arquivos disponíveis para download e crie uma interface de usuário personalizada para ele. Será mais simples e você controlará todo o processo.

Dê uma olhada em http://www.csharp-examples.net/download-files/ e em msdn docs no webclient http://msdn.microsoft.com/en-us/library/system.net.webclient.aspx

Minha sugestão é tentar o download síncrono como mais simples. Você pode obter ideias sobre se os parâmetros do Webclient estão incorretos ou se o arquivo está no formato incorreto ao tentar isso.

Aqui está uma amostra de código ..

 private void btnDownload_Click(object sender, EventArgs e) { string filepath = textBox1.Text; WebClient webClient = new WebClient(); webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed); webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); webClient.DownloadFileAsync(new Uri("http://mysite.com/myfile.txt"), filepath); } private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { progressBar.Value = e.ProgressPercentage; } private void Completed(object sender, AsyncCompletedEventArgs e) { MessageBox.Show("Download completed!"); } 

Uma solução muito mais simples seria baixar o arquivo usando o Chrome. Desta forma, você não precisa clicar manualmente no botão salvar.

 using System; using System.Diagnostics; using System.ComponentModel; namespace MyProcessSample { class MyProcess { public static void Main() { Process myProcess = new Process(); myProcess.Start("chrome.exe","http://www.com/newfile.zip"); } } }