[c#] Download file and automatically save it to folder

I'm trying to make a UI for downloading files from my site. The site have zip-files and these need to be downloaded to the directory entered by the user. However, I can't succeed to download the file, it just opens up from a temporary folder.

Code:

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

Full sourcecode: http://en.paidpaste.com/LqEmiQ

This question is related to c# file download save

The answer is


A much simpler solution would be to download the file using Chrome. In this manner you don't have to manually click on the save button.

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

My program does exactly what you are after, no prompts or anything, please see the following code.

This code will create all of the necessary directories if they don't already exist:

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

This code will download the given file to the given directory (after it has been created by the previous snippet:

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
    }

So using these two pieces of code you can create all of the directories and then tell the downloader (that doesn't prompt you to download the file to that location.


If you don't want to use "WebClient" or/and need to use the System.Windows.Forms.WebBrowser e.g. because you want simulate a login first, you can use this extended WebBrowser which hooks the "URLDownloadToFile" Method from the Windows URLMON Lib and uses the Context of the 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
        {
            /// <summary>
            /// 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.
            /// </summary>
            /// <param name="callerPointer">Pointer to caller object (AX).</param>
            /// <param name="url">String of the URL.</param>
            /// <param name="filePathWithName">String of the destination filename/path.</param>
            /// <param name="reserved">[reserved].</param>
            /// <param name="callBack">A callback function to monitor progress or abort.</param>
            /// <returns>0 for okay.</returns>
            /// 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);


            /// <summary>
            /// Download a file from the webpage and save it to the destination without promting the user
            /// </summary>
            /// <param name="url">the url with the file</param>
            /// <param name="destinationFullPathWithName">the absolut full path with the filename as destination</param>
            /// <returns></returns>
            public FileInfo DownloadFile(string url, string destinationFullPathWithName)
            {
                URLDownloadToFile(null, url, destinationFullPathWithName, 0, IntPtr.Zero);
                return new FileInfo(destinationFullPathWithName);
            }
        }
    }

Well, your solution almost works. There are a few things to take into account to keep it simple:

  • Cancel the default navigation only for specific URLs you know a download will occur, or the user won't be able to navigate anywhere. This means you musn't change your website download URLs.

  • DownloadFileAsync doesn't know the name reported by the server in the Content-Disposition header so you have to specify one, or compute one from the original URL if that's possible. You cannot just specify the folder and expect the file name to be retrieved automatically.

  • You have to handle download server errors from the DownloadCompleted callback because the web browser control won't do it for you anymore.

Sample piece of code, that will download into the directory specified in textBox1, but with a random file name, and without any additional error handling:

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

This solution should work but can be broken very easily. Try to consider some web service listing the available files for download and make a custom UI for it. It'll be simpler and you will control the whole process.


Take a look at http://www.csharp-examples.net/download-files/ and msdn docs on webclient http://msdn.microsoft.com/en-us/library/system.net.webclient.aspx

My suggestion is try the synchronous download as its more straightforward. you might get ideas on whether webclient parameters are wrong or the file is in incorrect format while trying this.

Here is a code sample..

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!");
}

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to file

Gradle - Move a folder from ABC to XYZ Difference between opening a file in binary vs text Angular: How to download a file from HttpClient? Python error message io.UnsupportedOperation: not readable java.io.FileNotFoundException: class path resource cannot be opened because it does not exist Writing JSON object to a JSON file with fs.writeFileSync How to read/write files in .Net Core? How to write to a CSV line by line? Writing a dictionary to a text file? What are the pros and cons of parquet format compared to other formats?

Examples related to download

how to download file in react js How do I download a file with Angular2 or greater Unknown URL content://downloads/my_downloads python save image from url How to download a file using a Java REST service and a data stream How to download file in swift? Where can I download Eclipse Android bundle? How to download image from url android download pdf from url then open it with a pdf reader Flask Download a File

Examples related to save

What is the difference between --save and --save-dev? Basic http file downloading and saving to disk in python? Save byte array to file Saving Excel workbook to constant path with filename from two fields PHP - get base64 img string decode and save as jpg (resulting empty image ) How to edit/save a file through Ubuntu Terminal Write and read a list from file How to do a "Save As" in vba code, saving my current Excel workbook with datestamp? How to dump raw RTSP stream to file? Saving images in Python at a very high quality