Download Files in ASP.NET MVC 3 using Controller Action

Posted by: Mahesh Sabnis , on 5/10/2012, in Category ASP.NET MVC
Views: 89668
Abstract: The FileResult action that comes out of box with ASP.NET MVC3 provides an easy to use abstraction for downloading files in an ASP.NET MVC application.

Last week I was conducting a training for one of my clients on ASP.NET MVC 3 features. They had a file server, hosting various types of reports and were using an ASP.NET Web Form application as a front-end to download the reports on the client machine. Now since they planned on migrating the ASP.NET WebForms to ASP.NET MVC, they expected a similar functionality in MVC too.

As most of you working on ASP.NET MVC know, the Views are directly controlled by controller action. Every action method from the controller class returns an ActionResult. This itself is an abstract class. We have several classes inherited from it and they are used in specific cases. One of the classes inherited from ActionResult is FileResult. This class is used to send binary file content to the response. In the following sample, we will see how we can leverage the FileResult action to download files in an ASP.NET MVC Web Application.

 

Step 1: Open VS2010 and create a new ASP.NET MVC 3 project, name it as ‘MVC3_Returning_Files’.

Step 2: In the project, add a new folder and name it as ‘Files’. Add couple of PDF files in it.

Step 3: Right-click on the Models folder and add a new class file, name it as ‘DataClasses.cs’. Add the following classes in it:

namespace MVC3_Returning_Files.Models
{
    public class DataClasses
    {
        public List<FileNames> GetFiles()
        {
           
            List<FileNames> lstFiles = new List<FileNames>();
            DirectoryInfo dirInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/Files"));
           
            int i = 0;
            foreach (var item in dirInfo.GetFiles())
            {

                lstFiles.Add(new FileNames() {

                FileId = i + 1, FileName = item.Name, FilePath = dirInfo.FullName+@"\"+item.Name});
                i = i + 1;
            }
           
            return lstFiles;
        }
    }

    public class FileNames
    {
        public int FileId { get; set; }
        public string FileName { get; set; }
        public string FilePath { get; set; }
    }
}

The class DataClasses contains ‘GetFiles’ method. This method reads all files from the ‘Files’ folder created in Step 2 and returns a list of files with information as Field, FileName and FilePath declared in FileNames class.

Step 4: Add a new ‘ReportsController’ with the following action methods:

namespace MVC3_Returning_Files.Controllers
{
    public class ReportsController : Controller
    {
        DataClasses objData;

        public ReportsController()
        {
            objData = new DataClasses();
        }

        //
        // GET: /Reports/

        public ActionResult Index()
        {
            var files = objData.GetFiles(); 
            return View(files);
        }

      
        public FileResult Download(string id)
        {
            int fid = Convert.ToInt32(id);
            var files = objData.GetFiles();
            string filename = (from f in files
                               where f.FileId == fid
                               select f.FilePath).First();
            string contentType = "application/pdf";
            //Parameters to file are
            //1. The File Path on the File Server
            //2. The content type MIME type
            //3. The parameter for the file save by the browser
            return File(filename, contentType,"Report.pdf");
        }

    }
}

 

The ‘Download’ action method accepts id (FileId) from the view and queries the Files List returned from the GetFiles method. After querying the List of files, it retrieve the file path. It also defines content type which is MIME type defined content header. This information is required by the browser to decide how to handle file. In this case, it is defined as  aPDF. The method returns an object of the type ‘FilePathResult’. This is the class inherited from FileResult. FilePathResult accepts three parameters. The first is the file path of the file which is to be downloaded. The second is the content type. The third parameter is the Download file name. This is an optional parameter, but if passed, then the browser will show the download effect.

Step 5: Add a new Index View using Index action which has some Razor code as shown below:

model IEnumerable<MVC3_Returning_Files.Models.FileNames>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
     <th>
            FileId
        </th>
        <th>
            FileName
        </th>
    </tr>

@foreach (var item in Model) {
    <tr>
    <td>
            @Html.DisplayFor(modelItem => item.FileId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.FileName)
        </td>
        <td>
            @Html.ActionLink("Download", "Download", new { id = item.FileId })
         
        </td>
    </tr>
}

</table>

 

Step 6: Add the following Action link in the menucontainer <div> of the _Layout.cshtml:

<li>@Html.ActionLink("Reports", "Index", "Reports")</li>

Step 7: Run the application and you will find the Report menu. After clicking on it, the Index page will display all the Files as shown below:

MVC 3 Download File

Click on the Download link and you will get a download box as shown below (Note: I am using IE9)

image

Conclusion

The FileResult action that comes out of box with ASP.NET MVC3 provides an easy to use abstraction for downloading files in an ASP.NET MVC application.

The entire source code of this article can be downloaded from GitHub

Give me a +1 if you think it was a good article. Thanks!
Recommended Articles
Mahesh is having 10 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet




Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Naresh on Friday, May 11, 2012 2:32 AM
Niceeeee
Comment posted by mathew on Tuesday, June 12, 2012 1:02 AM
How can i add multiple files to a single zip file and permits the users to download this zip file?
Comment posted by Doctor Benigno on Monday, June 18, 2012 7:10 AM
seems there is a problem in step 5

the view croaks with a CS1963 error , the expression tree cannot contain a dinamic operation.

Seems that the use of the @Html.DisplayFor helper needs something more to run smoothly. If i comment out the uses of the helper , the example runs just fine.

@Html.DisplayFor(modelItem => item.FileId)
and
@Html.DisplayFor(modelItem => item.FileName)

need to be tweaked into something else.
Comment posted by meganathan subramani on Saturday, June 23, 2012 5:36 AM
Hi,

I can upload more than 5MB size files, but i can't able to download that files. Give me the solution.
Thanks,
Comment posted by a on Tuesday, July 03, 2012 5:25 AM
a
Comment posted by Pat M on Monday, July 09, 2012 7:18 PM
Thanks for the great tutorial.  I had been trying to adjust the router to enable downloads of zip files but your method makes a lot more sense.  I appreciate the help.
Comment posted by Triven on Wednesday, July 18, 2012 5:44 AM
Hi Mahesh,

I am getting the following error
The current request for action 'Download' on controller type mycontroller is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Download() on type myproject.Controllers.mycontroller
System.Web.Mvc.FileResult Download(System.String) on type myproject.Controllers.mycontroller

Need help to resolve the same...
Comment posted by Triven on Wednesday, July 18, 2012 6:39 AM
Hi Mahesh,

Just needed to have different names for FileResult and ActionResult
Comment posted by Triven on Wednesday, July 18, 2012 6:42 AM
Hi Mahesh,

First issue is resolved , but what if i want to download the file with it's actual extension.?

Thanks.
Comment posted by G.NAGA HARISH CHOUDARY on Friday, October 05, 2012 7:34 AM
hi sir, iam very happy withur posted  data ,( regarding the uploading, i want to know about how to download  plz  post as soon as possible)

THANKING YOU,
G.N.H.C  
Comment posted by Amit on Tuesday, October 23, 2012 2:06 AM
This is Very use full Post Thanks.
Comment posted by Mahesh on Tuesday, October 23, 2012 3:46 PM
Very very very usefull.. Thanks a lot for the article.. You saved lot of my time.
Comment posted by pradeep gusain on Tuesday, October 30, 2012 2:21 AM
@ Doctor Benigno
use  <td> @item.FileId </td>
     <td> @item.FileName </td>

instead of
  <td>
            @Html.DisplayFor(modelItem => item.FileId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.FileName)
        </td>
Comment posted by gfgf on Tuesday, February 12, 2013 8:37 AM
fggfg
Comment posted by praveen vyas on Sunday, March 17, 2013 6:47 AM
really nice blog
Comment posted by Alex Leblois on Saturday, May 18, 2013 4:47 AM
Hi!

This is a nice artile. Thanks for sharing your knowlodge because some time need to download files in a single zip folder

because this is a better way to download multiple files. I have findout some other links that's also helpful for

developers.

http://www.campusmvp.net/blog/asp-net-mvc-return-of-zip-files-created-on-the-fly

http://www.mindstick.com/Blog/439/File%20download%20in%20zip%20Folder%20in%20ASP%20NET%20MVC%204

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel