Blog categories

File upload in ASP.NET MVC

File upload in ASP.NET MVC

 

Uploading a single file

 

Let’s start with the view. Here’s a form that will post back to the current action.

 

<form action="" method="post" enctype="multipart/form-data">
  
  <label for="file">Filename:</label>
  <input type="file" name="file" id="file" />

  <input type="submit" />
</form>

 

Here’s the action method that this view will post to which saves the file into a directory in the App_Data folder named “uploads”.

 

[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {
            
  if (file.ContentLength > 0) {
    var fileName = Path.GetFileName(file.FileName);
    var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
    file.SaveAs(path);
  }
            
  return RedirectToAction("Index");
}

 

Notice that the argument to the action method is an instance of HttpPostedFileBase. ASP.NET MVC 2 introduces a new value providers feature which I’ve covered before.

 

Whereas model binders are used to bind incoming data to an object model, value providers provide an abstraction for the incoming data itself.

 

In this case, there’s a default value provider called the HttpFileCollectionValueProvider which supplies the uploaded files to the model binder.Also notice that the argument name, file, is the same name as the name of the file input. This is important for the model binder to match up the uploaded file to the action method argument.

 

Uploading multiple files

 

In this scenario, we want to upload a set of files. We can simply have multiple file inputs all with the same name.

 

<form action="" method="post" enctype="multipart/form-data">
    
  <label for="file1">Filename:</label>
  <input type="file" name="files" id="file1" />
  
  <label for="file2">Filename:</label>
  <input type="file" name="files" id="file2" />

  <input type="submit"  />
</form>

 

Now, we just tweak our controller action to accept an IEnumerable of HttpPostedFileBase instances. Once again, notice that the argument name matches the name of the file inputs.

 

[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> files) {
  foreach (var file in files) {
    if (file.ContentLength > 0) {
      var fileName = Path.GetFileName(file.FileName);
      var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
      file.SaveAs(path);
    }
  }
  return RedirectToAction("Index");
}

 

Yes, it’s that easy. :)

from http://www.haacked.com