Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to Download Large Files from ASP.NET Web Forms or MVC?

0.00/5 (No votes)
15 Nov 2014 2  
How to download large files from ASP.NET Web Forms (Download.aspx or Download.ashx) or ASP.NET MVC

Introduction

Sometimes in ASP.NET Web Forms or ASP.NET MVC applications, you put some of your secured files in a secured folder such as App_Data because you do not want users to have direct access to these files for downloading. In this situation, you write a Download.aspx file or Download.ashx http handler (in ASP.NET Web Forms), or create a download action (in ASP.NET MVC) that users can just download these files with these capabilities. There are a lot of source codes for this situation. But! If the size (length) of these files be large, for example, over 100 MB! We have two main problems.

First, we caused a very huge overhead to the server’s CPU and RAM and second, if some user tried to download a large file and after a few seconds he avoided to download the file resume, your application does not know it!

So in the below source code, I optimized the download progress, so the code get a few bytes from the file and send it to the user (client). By the way, if after a few seconds, the user (client) avoided to download the file resume, the below code recognizes it and stops sending the file resume.

Note: The below code is an action for ASP.NET MVC applications, But you can write it in Download.aspx or Download.ashx files in your ASP.NET Web Forms applications.

Using the Code

/// <summary>
/// Download Large Files! For example more than 100MB!
/// </summary>
public void Download(int id)
{
    // **************************************************
    string strFileName =
        string.Format("{0}.zip", id);

    string strRootRelativePathName =
        string.Format("~/App_Data/Files/{0}", strFileName);

    string strPathName =
        Server.MapPath(strRootRelativePathName);

    if (System.IO.File.Exists(strPathName) == false)
    {
        return;
    }
    // **************************************************

    System.IO.Stream oStream = null;

    try
    {
        // Open the file
        oStream =
            new System.IO.FileStream
                (path: strPathName,
                mode: System.IO.FileMode.Open,
                share: System.IO.FileShare.Read,
                access: System.IO.FileAccess.Read);

        // **************************************************
        Response.Buffer = false;

        // Setting the unknown [ContentType]
        // will display the saving dialog for the user
        Response.ContentType = "application/octet-stream";

        // With setting the file name,
        // in the saving dialog, user will see
        // the [strFileName] name instead of [download]!
        Response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName);

        long lngFileLength = oStream.Length;

        // Notify user (client) the total file length
        Response.AddHeader("Content-Length", lngFileLength.ToString());
        // **************************************************

        // Total bytes that should be read
        long lngDataToRead = lngFileLength;

        // Read the bytes of file
        while (lngDataToRead > 0)
        {
            // The below code is just for testing! So we commented it!
            //System.Threading.Thread.Sleep(200);

            // Verify that the client is connected or not?
            if (Response.IsClientConnected)
            {
                // 8KB
                int intBufferSize = 8 * 1024;

                // Create buffer for reading [intBufferSize] bytes from file
                byte[] bytBuffers =
                    new System.Byte[intBufferSize];

                // Read the data and put it in the buffer.
                int intTheBytesThatReallyHasBeenReadFromTheStream =
                    oStream.Read(buffer: bytBuffers, offset: 0, count: intBufferSize);

                // Write the data from buffer to the current output stream.
                Response.OutputStream.Write
                    (buffer: bytBuffers, offset: 0,
                    count: intTheBytesThatReallyHasBeenReadFromTheStream);

                // Flush (Send) the data to output
                // (Don't buffer in server's RAM!)
                Response.Flush();

                lngDataToRead =
                    lngDataToRead - intTheBytesThatReallyHasBeenReadFromTheStream;
            }
            else
            {
                // Prevent infinite loop if user disconnected!
                lngDataToRead = -1;
            }
        }
    }
    catch { }
    finally
    {
        if (oStream != null)
        {
            //Close the file.
            oStream.Close();
            oStream.Dispose();
            oStream = null;
        }
        Response.Close();
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here