Wednesday, October 8, 2008

File Upload/Download using C#

The System.Net namespace contain most of the .NET base class that deal with networking. The System.Net namespace is generally concerned with higher-level operations. Example; download/upload files, making requests using HTTP & other protocols etc.

To carry out fairly simple operations such as requesting a file from a URL, the easiest method is to use the System.Net.WebClient class. Code snippet for downloading a file is given below.

private void DownloadFile(string source, string target)
{
    using (WebClient wcDownload = new WebClient())
    {
        try
        {
            // Create a request to the file we are downloading
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(source);

            // Set default authentication for retrieving the file
            webRequest.Credentials = CredentialCache.DefaultCredentials;

            // Retrieve the response from the server
            HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();

            // Ask the server for the file size and store it
            Int64 fileSize = webResponse.ContentLength;

            // Open the URL for download
            using (Stream responseStream = wcDownload.OpenRead(source))
            {
                if (Directory.Exists(target))
                {
                    // Given path represents directory. Append filename
                    string fileName = Path.GetFileName(source);

                    if (!target.EndsWith(Path.DirectorySeparatorChar.ToString()))
                        target += Path.DirectorySeparatorChar.ToString();

                    target += fileName;
                }

               // Create a new file stream where we will be saving the data
                using (Stream localStream = new FileStream(target,
                                                                        FileMode.Create,
                                                                        FileAccess.Write,
                                                                        FileShare.None))
                {
                    // It will store the current number of bytes we retrieved from the server
                    int bytesSize = 0;

                    // A buffer for storing and writing the data retrieved from the server
                    byte[] downBuffer = new byte[2048];

                    // Loop through the buffer until the buffer is empty
                    while ((bytesSize = responseStream.Read(downBuffer, 0, downBuffer.Length)) > 0)
                    {
                        // Write the data from the buffer to file
                        localStream.Write(downBuffer, 0, bytesSize);
                    } 
                }
            }
        }
        catch
        {
            throw;
        }
    }
}

The above code uses CredentialCache.DefaultCredentials, which represents credentials of the currently logged in user. If the file to be downloaded requires different username/password, it can be passed by creating a NetworkCredential object with the corresponding username/password and then by assigning it instead of the default credentials.

There is a simpler version of the above code. We can use the DownloadFile() of the WebClient class for downloading a file. In this case, since everything is handled by the WebClient class, we will not have any control over the download process. Example:

WebClient client = new WebClient ();
client.DownloadFile(source, target);

Sometimes, it may not be necessary to download and save the file locally for processing. In such a case, where the application works by retrieving the data from the URL and processing it straight away, the OpenRead() of WebClient class can be used. Code snippet is given below.

private string GetDataFromURL(string url)
{
    StringBuilder data = new StringBuilder();

    try
    {
        using (WebClient client = new WebClient())
        {
            using (Stream stream = client.OpenRead(url))
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    string line;

                    while ((line = reader.ReadLine()) != null)
                    {
                        data.Append(line);
                    }

                    reader.Close();
                }

                stream.Close();
            }
        }
    }
    catch
    {
        throw;
    }

    return data.ToString();
}

Just to try the above code; if a call is made to the GetDataFromURL() as shown below, it will fetch the raw HTML data for this blog.

GetDataFromURL("http://techblog-giri-csharp.blogspot.com")

The WebClient class also features UploadFile() and UploadData() methods. The diffrence between them is that UploadFile() uploads a specified file given the file name, whereas UploadData() uploads binary data, which is supplied as an array of bytes. Example code for uploading a file is given.

private void UploadFile(string source, string target)
{
    try
    {
        using (WebClient wcCopy = new WebClient())
        {
            // Set default authentication
            wcCopy.Credentials = CredentialCache.DefaultCredentials;

            // Upload file
            wcCopy.UploadFile(target, "PUT", source);
        }
    }
    catch
    {
        throw;
    }
}

Here also, a NetworkCredential object can be used instead of the default credentials, if the file to be downloaded requires a different username/password.

No comments: