Monday, 9 September 2013

MVC Tips : Uploads and Downloads files in ASP.Net MVC

Click Here to Download UploadAndDownloadFileInMVC.zip Example.
 
In many software application uploading and downloading files are required. There are very easy way to upload and download file in ASP.Net MVC framework.

Here is step by step example of how to implement upload and download functionality in MVC.

In this example we will also demonstrate how to change encoding type of form, how to apply CSS class to "Button" and "ActionLink" control and also How to apply style attribute with value.

STEP 1 : Add Upload View
Here is HTML of Uplod view file.

@using (Html.BeginForm("Index", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ 
    @Html.AntiForgeryToken() 
     <fieldset>
         <legend>Upload a file</legend>
        @Html.Raw(ViewBag.Message)
            <div class="editor-field">
                    @Html.TextBox("file", "", new { type = "file" }) 

            </div>
            <div class="editor-field">
                <input type="submit" value="Upload File" class="button_example" />
            </div>
         @Html.ActionLink("Go To Download Page","Index","Download",null, new {@class = "button_example",style="float:right"})
    </fieldset> 
} 



In this, you can see that we set enctype = "multipart/form-data", this is because we want to post binary data of file to our server. It is also sending the normal text data. By default, enctype is 'text-plain'. For uploading file you must set enctype = "multipart/form-data" otherwise uploading does not work. After running the Upload page you can view it's HTML source in browser. This will render our basic html code.

Now when user select file from browse button and click on UPLOAD button at that time data will post on "Index" action method of "Upload" Controller.

STEP 2 : Add Upload Controller

Here is Upload Controller Code File.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace UploadAndDownloadFileInMVC.Controllers
{
    public class UploadController : Controller
    {

        public ActionResult Index()
        {
            return View();
        }

        

        [HttpPost]
        public ActionResult Index(HttpPostedFileBase file) 
        { 
            try 
            { 
                if (file.ContentLength > 0) 
                { 
                    var fileName = Path.GetFileName(file.FileName); 
                    var path = Path.Combine(Server.MapPath("~/App_Data/Images"), fileName); 
                    file.SaveAs(path); 
                } 
                ViewBag.Message = "Upload successful"; 
                return View();
            } 
            catch 
            { 
                ViewBag.Message = "Upload failed";
                return View();
            } 
        }

    }
}

In this code you can see that on 'Index' method we apply '[HttpPost]' attribute. This will indicate that, this method accepts posted data. By default, method attribute is 'GET'.

This 'Index' method accept one argument whose type is 'HttpPostedFileBase'. This means our posted file data come in this, this argument and we can get it's binary value in our 'file' variable.
Note : If we need to upload multiple files from page at that time use IEnumerable instead of a single HttpPostedFile. After that, you need to looping that collection and access each file.

In this method you can see that we are getting file name of that posted file and save to physical location to 'APP_CODE' folder. But for that you need to write permission to this folder.

If your uploading view contains the normal data and posted file binary data at that time in your controller you can set both parameters like Model object and HttpPostedFileBase object.

Like below example :
public ActionResult Upload( Customer Customer, HttpPostedFileBase file ) {… }

STEP 3 : Add Download View

Here is Download View code file.
@model List<string>
<h2>Downloads</h2>
<table  border="1">
    <tr>
        <th>File Name</th>
        <th>Link</th>
    </tr>
    
    @for (var i = 0; i <= Model.Count - 1; i++)
    {
     <tr>
         <td>
             @Model[i].ToString();
         </td>
         <td>
             @Html.ActionLink("Download","DownloadFile", new {FileName=@Model[i].ToString()})
         </td>
     </tr>
    }

</table>
@Html.ActionLink("Go To Upload Page","Index","Upload",null, new {@class = "button_example",style="float:right;margin-top:80px;position:absolute;right:0;top:0;margin-right:10px"})

In this view we display grid and in this grid there are two columns one is for the file name and another is Downlod link to download the file.

You can see that on 'Download' link we set 'Download' controller and 'DownloadFile' as an action of that link. So when user click on 'Download' link DownloadFile method call of Download controller and server read that file and set to the browser at that time use can see the download dialog box of that file.

In this, you can see that we add one 'Go To Upload Page' button. This is an ActionLink button. This button is used for simple navigation between upload and download page.

In this, you can see that how we can apply both CSS Class and Style attribute together.

STEP 4 : Add Download Controller

Here is Download Controller Code File.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace UploadAndDownloadFileInMVC.Controllers
{
    public class DownloadController : Controller
    {
        //
        // GET: /Download/

        public ActionResult Index()
        {
            var dir = new System.IO.DirectoryInfo(Server.MapPath("~/App_Data/Images/"));
            System.IO.FileInfo[] fileNames = dir.GetFiles("*.*");
            List<string> items = new List<string>();
            foreach (var file in fileNames)
            {
                items.Add(file.Name);
            }
            return View(items); 

        }

        public FileResult DownloadFile(string FileName)
        {
            return File("~/App_Data/Images/" + FileName, System.Net.Mime.MediaTypeNames.Application.Octet, FileName);
        } 

    }
}

In this, you can see that two action methods one is 'Index' and another is 'DownloadFile'.

'Index' methods call at the time of download view render, in this method we are getting list of files from our 'APP_Code' folder which we uploaded and displayed in the form of grid.

Now when user click on 'Download' link against file name at that time 'DownloadFile' method call. This method returns type is 'FileResult'. In this method it will return file according to our given file path.

There are other various return type of file such as a FileContentResult, FilePathResult and FileStreamResult. You can use any of this depending on your requirement.

FileContentResult : When you want byte array of file content.
return new FileContentResult(byteArray, "image/jpeg"); 

FilePathResult : Returns a file on the disk when you want to via a file path.
return new FilePathResult("~/App_Data/Images/" + FileName, System.Net.Mime.MediaTypeNames.Application.Octet);

FileStreamResult : Sends a stream to the response.
return new FileStreamResult(new FileStream("<your path>", FileMode.Open), "image/jpeg");

Below are the screenshot of this example : 

(To view original image , click on image)


After Click on 'Browse' Button :

(To view original image , click on image)

After Selecting File From Browse Window :

(To view original image , click on image)
After Click on Upload File Button : 

(To view original image , click on image)
Listing Of Files in the grid for Download : 

(To view original image , click on image)
After Click On Download Link Download Dialog Box Open : 

(To view original image , click on image)


Below are the books that you would like :

8 comments:

  1. big help. =) thank you.

    ReplyDelete
  2. A error is occuring as model.count in download view is returnig null.Can you suggest?

    ReplyDelete
    Replies
    1. Hi,
      Can you suggest exact in which step error is occurred ?

      Delete
  3. Thanks Jayesh, it actually worked on one try :)

    ReplyDelete
  4. It can not work on Azure hosting bro.

    ReplyDelete