Need a simple CRM and Project Management system?
Check out JobNimbus - CRM for Contractors and Service Professionals.

ASP.NET Download File to Web Browser

Many times you will want to allow a user to click on a link on your ASP.NET page and then cause a file to be downloaded to the user. This is common for operations like exporting a file as a CSV or PDF. But if the file to download is not in a publicly / web accessible location, then it is not as simple as just putting a hyperlink to the file. Also, if you want to add security to the access of the file (such as checking for a logged in user), you will want to protect these files and they will not be able to be hyperlinked directly in your page. Instead, these files need to be "streamed" back to the user when a button is clicked.

There are several things to keep in mind when streaming / downloading a file in ASP.NET to the browser.

  • Ideally, you should know the MIME type of the file you are downloading to the user. This is useful because if you specify the MIME type, then the default program for that type will automatically attempt to open that file when the user is presented with the "open" or "save" dialog.
  • When downloading the file, you must first clear any existing stream so that you do not get characters from your ASP.NET page included in the file bytes (this will cause the file to be corrupted if you forget to clear the Response first).

Below is a simple class that attempts to determine the MIME type of a given file and then allows you to stream this file back so that users can download the file through their browser. This first method tries to determine the MIME type of the file using the file's name and extension. It then matches that extension against common known file types to find the MIME type. If not found, the default "octet-stream" MIME is used (which basically just tells the browser that a binary file is coming of unknown MIME type) so the browser can at least show the "open" or "save" dialog.

/// <summary>
/// Gets the MIME type of the file name specified based on the file name's
/// extension.  If the file's extension is unknown, returns "octet-stream"
/// generic for streaming file bytes.
/// </summary>
/// <param name="sFileName">The name of the file for which the MIME type
/// refers to.</param>
public string GetMimeTypeByFileName(string sFileName)
{
    string sMime = "application/octet-stream";

    string sExtension = System.IO.Path.GetExtension(sFileName);
    if (!string.IsNullOrEmpty(sExtension))
    {
        sExtension = sExtension.Replace(".", "");
        sExtension = sExtension.ToLower();

        if (sExtension == "xls" || sExtension == "xlsx")
        {
            sMime = "application/ms-excel";
        }
        else if (sExtension == "doc" || sExtension == "docx")
        {
            sMime = "application/msword";
        }
        else if (sExtension == "ppt" || sExtension == "pptx")
        {
            sMime = "application/ms-powerpoint";
        }
        else if (sExtension == "rtf")
        {
            sMime = "application/rtf";
        }
        else if (sExtension == "zip")
        {
            sMime = "application/zip";
        }
        else if (sExtension == "mp3")
        {
            sMime = "audio/mpeg";
        }
        else if (sExtension == "bmp")
        {
            sMime = "image/bmp";
        }
        else if (sExtension == "gif")
        {
            sMime = "image/gif";
        }
        else if (sExtension == "jpg" || sExtension == "jpeg")
        {
            sMime = "image/jpeg";
        }
        else if (sExtension == "png")
        {
            sMime = "image/png";
        }
        else if (sExtension == "tiff" || sExtension == "tif")
        {
            sMime = "image/tiff";
        }
        else if (sExtension == "txt")
        {
            sMime = "text/plain";
        }
    }

    return sMime;
}

This second method does the downloading of the file by streaming the file back to the browser:

/// <summary>
/// Streams the bytes specified as a file with the name specified using HTTP to the 
/// calling browser.
/// </summary>
/// <param name="sFileName">The name of the file as it will apear when the user
/// clicks either open or save as in their browser to accept the file
/// download.</param>
/// <param name="fileBytes">The file as a byte array to be streamed.</param>
public void StreamFileToBrowser(string sFileName, byte[] fileBytes)
{
    System.Web.HttpContext context = System.Web.HttpContext.Current;
    context.Response.Clear();
    context.Response.ClearHeaders();
    context.Response.ClearContent();
    context.Response.AppendHeader("content-length", fileBytes.Length.ToString());
    context.Response.ContentType = GetMimeTypeByFileName(sFileName);
    context.Response.AppendHeader("content-disposition", "attachment; filename=" + sFileName);
    context.Response.BinaryWrite(fileBytes);

    // use this instead of response.end to avoid thread aborted exception (known issue):
    // http://support.microsoft.com/kb/312629/EN-US
    context.ApplicationInstance.CompleteRequest();
}

To use these methods, you might write this kind of code in an ASP.NET button click event:

// the file name to get
string fileName = "somefilename.txt";
// get the file bytes to download to the browser
byte[] fileBytes = System.IO.File.ReadAllBytes("C:\\Some Path\\" + fileName);
// NOTE: You could also read the file bytes from a database as well.

// download this file to the browser
StreamFileToBrowser(fileName, fileBytes);

Exactly what I was looking for

Clean, easy to implement, and thorough.

docx problem

Really its very good..!! Working perfect for my code.
Thanks lot.

From:
Ganesh

asp.net developer

Really very very nice code.

ajax

' REGISTER BUTTON AJAX
ScriptManager.GetCurrent(Page).RegisterPostBackControl(Button1)

very nice code by pawan

This is very nice code you did very good job

Thanks ! Wery good article !

Thanks ! Wery good article ! Helped !