JumpStart # 42 – Download file in ASP.Net MVC

In this jumpstart, we are going to see how to download a file from server to client browser in ASP.Net MVC using a RouteHandler . A RouteHandler will be created to handle all the requests made to a particular URL with specific route data (part of URL itself) to identify the file requested and will return a particular HttpHandler for the request. HttpHandler is going to find the file on the server, set it into the Response of HttpContext and finally send the response back to the client (typically a browser, but it can be anything).

To get started, create an ASP.Net MVC4 Web Application project in Visual Studio (for this tutorial I am using VS 2012, we can use any other version as well). Now we will proceed to create a RouteHandler which will serve all the file requests.

// Route Handler
public class FileHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        // return File HttpHandler (created below)
        return new FileHttpHandler();
    }
}

// HttpHandler to server files
public class FileHttpHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        // Get Request Context
        var ctx = HttpContext.Current.Request.RequestContext;

        // Get Route Data
        var imageFile = ctx.RouteData.Values["file"].ToString();

        // Get path to the requested file (for demo we are using FileStorage folder of root directory)
        var path = context.Server.MapPath("~/FilesStorage/") + imageFile;

        // Set the file in response
        context.Response.Clear();
        context.Response.AddHeader("content-disposition",
            string.Format("attachment; filename=\"{0}\"", Path.GetFileName(path)));
        context.Response.ContentType = "application/octet-stream";
        context.Response.TransmitFile(path);
        context.Response.End();
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

We need to register the newly created RouteHandler as shown below in RouteConfig.cs. Order of registration is very important, otherwise every file request will be interpreted by MVC with the default route.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.Add("FileRoute", new Route("files/{file}", new FileHandler()));

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Above route will make sure that any request made to ‘/files/*.*’ path will be handled by registered RouteHandler.

To make sure our RouteHandler fires for all file requests which matches the URL pattern, we need to register UrlRouting Module without preCondition as shown below, otherwise requests will be treated as static file requests and might fail because of no physical file existence.

<modules>
  <remove name="UrlRoutingModule-4.0" />
  <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
</modules>

For testing, I placed data.doc in FilesStorage folder under application root folder. Run the application and we can use fiddler to make the request for the file and check the response. We can also use browser to make the request and download the file.

image

That’s it for now. Happy Coding and Stay Tuned!!!

You may also like...