How to download files from server to client using a Generic Handler

 

In this article, we see how to provide a download option (say for example to download images) to the users of our website. In accomplishing the requirement we use a Generic HttpHandler – which handles all the requests made for the download. For demonstration purpose we take some images and display them using a Datalist, in which we do provide an option to download. On download option click, the generic handler will process the request and displays an dialog in the client questioning client either to save or open the file, accordingly corresponding action will be taken place.

NOTE :-
  1. Most of the code is self-explanatory and easily understandable (with a quick debugging).
  2. For demo, some sample images are placed in a folder – ‘images’ – under the root directory of the website.

To get started, create a sample website in VS 2010, Add a page (Default.aspx) and a Generic Handler(DownloadHanlder.ashx) to the website (by selecting ‘Add New Item’ from ‘Website’ option in the toolbar). Place sample images in the ‘images’ folder under the root directory of the website. The complete folder structure of the website is as shown in the bottom figure. Once the afore said procedure is done, place the code shown below in respective files.

================================================================================================

Default.aspx

This page renders the images (of ‘images’ folder) along with a download option which points to generic handler)

================================================================================================

<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        // Iterate through the images (only files with extension .jpg) in the 'images' folder, and bind them to the Datalist
        
        ArrayList al = new ArrayList();
        foreach (string file in Directory.GetFiles(Server.MapPath("images/")))
        {
            if (Path.GetExtension(file) == ".jpg")
            {
                al.Add(Path.GetFileName(file));
            }
        }
        DataList1.DataSource = al;
        DataList1.DataBind();
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:DataList ID="DataList1" runat="server" RepeatDirection="Horizontal">
        <ItemTemplate>
        <center>
            <asp:Image ID="Image1" ImageUrl='<%#"images/" + Container.DataItem %>' runat="server" Width="150" Height="150" />
            <br />
            <a href='<%#string.Format("DownloadHandler.ashx?ImageName={0}",Container.DataItem)%>'>Download</a>
            </center>
        </ItemTemplate>
        </asp:DataList>
    </div>
    </form>
</body>
</html>

================================================================================================

DownloadHandler.ashx

This handler handles all the requests for the downloads.

================================================================================================

<%@ WebHandler Language="C#" Class="DownloadHandler" %>

using System;
using System.Web;

public class DownloadHandler : IHttpHandler 
{    
    public void ProcessRequest (HttpContext context) 
    {
        string file = "";
        
        // get the file name from the querystring
        if (context.Request.QueryString["ImageName"] != null)
        {
            file = context.Request.QueryString["ImageName"].ToString();
        }
        
        string filename = context.Server.MapPath("~/images/" + file);
        System.IO.FileInfo fileInfo = new System.IO.FileInfo(filename);

        try
        {
            if (fileInfo.Exists)
            {
                context.Response.Clear();
                context.Response.AddHeader("Content-Disposition", "attachment;filename=\"" + fileInfo.Name + "\"");
                context.Response.AddHeader("Content-Length", fileInfo.Length.ToString());
                context.Response.ContentType = "application/octet-stream";
                context.Response.TransmitFile(fileInfo.FullName);
                context.Response.Flush();
            }
            else
            {
                throw new Exception("File not found");
            }
        }
        catch (Exception ex)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write(ex.Message);
        }
        finally
        {
            context.Response.End();
        }
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
}

================================================================================================

Folder Structure

The website folder structure in the Solution Explorer of VS 2010.

================================================================================================

DownloadHandler-FolderStructure

================================================================================================

OUTPUT

================================================================================================

Before Download option is pressed –

BeforeDownload-DownloadHandler

After Download option is pressed –

AfterDownload-DownloadHandler

Disclaimer:

All coding and suggestions made in the above discussion is strictly in point of view of the author. It is neither mentioned any where nor even concluded that this is the only possible way to go with, as there will be always a chance for a new approach in achieving the same requirement (in context of programming). The above mentioned code is strictly written and explained for the sake of new comers to C# and ASP.NET world.

You may also like...

4 Pingbacks/Trackbacks

  • Gaurang

    Hi,

    I trid this code in my silverlight application but it is not working my code is here.

    From Xaml.cs file code
    ————————————
    HtmlPage.Window.Eval(
    “window.open(‘DownloadHandler.ashx?UserId=” + App.CurrentUser.UserId + “&DocumentId=” + crmDocument.DocumentId + “‘);”);

    ———————————————-
    in ‘DownloadHandler.ashx.cs Code is same as above

    In firefox it is working but in IE 7.0 It is not working.

    After publishing code it also gives error like

    Line 1:

    Please reply me on my email id.

    Thanks,
    Gaurang

  • Shwetamber Chourey

    Hi Ravi,

    Nice Article. But i have a Problem. When I am put the target in anchor tag or LinkButton Controll Then Download is not working. My Requirement is Download should open in new window or If Exception occurs then error will display in new window.

    Can you explain why it is happning . Please send me mail if you read this comment.

    Thanks & regards
    Shwetamber Chourey

  • RamiVemula

    @Chourey –

    I will get back to you once I have free time to look into the problem..

    Thanks,
    Rami.

  • Pingback: Taylor Lautner Workout Routine()

  • Pingback: Chicken Coops()

  • Pingback: silver mercury dime()

  • Sya

    this is good article and usefull to learn things from it ,
    if we want to add number of downloads counter to each photo , how we do it .. could you please explain for us ..
    many thanks

  • RamiVemula

    @Sya – In that case you need to have a database and you need to track it. Say you have all image details in database and then you need to update the column for number of downloads.

  • sya

    Thank you very much for you reply actually im beginner and need more help from you …
    if you can explain two things for me in details it will be great and much appreciated :
    1- if i have a database contain a table , and this table consist of ID , PictureName , PictureLink, Details , DownloadCounter .

    if i have a grid view for this table and want to mix your code to this grid view how we do it ?

    2- how to increase the number inside Download Counter field each time the image become download ..

    hope you can put complete project about this ..

    REgards

  • RamiVemula

    @Sya – You need to write a Stored Procedure which will be called before downloading, in there access the column Downloadcounter and increment it, then return all the picture details to the C# code. In the C# code later you can have Response Headers configured for the same and make it downloaded.

    Thanks,

  • Sya

    Thank you very much for the replay ,
    could you please put a compelete tutorial about this article

    much apreciated …

  • RamiVemula

    @Sya – I would love to, but I am bit busy these days with lot of work. So please dont be dependent on me.

  • Ashi

    Good One

  • Hetram

    I am using generic handler to download file.
    If i try to use context.Response.Cache.SetCacheability(HttpCacheability.NoCache); then the handler gives error.
    But if i comment the above line, the download handler work fine but most of the documents are getting corrupted.
    Can you suggest some work around for this issue.

  • Pingback: Downloading files from a server to client, using ASP.Net, when file size is too big for MemoryStream using Generic Handlers (ashx) | www.davidarodriguez.com()

  • modeste

    hi , thank you so much for this explanation, now i have a problem of how i can download using a button in a datalist view a file from a database(in a file in a table) i have tried many time but in vain. can you help me? thanks

  • João Paulo

    Great sample.Congratulations.
    Thank you.