File uploads and MVC Controllers
August 27th, 2010
Last week I had to implement some functionality to support uploading images to an MVC 2 application and then subsequently display them. Naturally there are a mountain of blog posts on this topic but I was unable to find anything comprehensive that covered everything that I needed on both the client and server side. What follows is my attempt to fill that hole.
My constraints were:
I am simply attaching an change event handler the the <input type=”file” /> control. The event handler does two things:
The imaginatively named Entity could not be simpler:
In a production scenario you are using probably using an O/RM such as NHibernate. In this case you will want to deviate from what I have above and store the uploaded file in a different entity. This is to avoid having to load the binary data for the file each time you access the entity. Note that NHibernate 3 supports (to a limited degree) lazy loading properties. However even if you are utilizing this feature you still want to make sure that the binary data is stored in a different table in the underlying RDBMS so that any full table scans (for example if you are performing some type of aggregation) don’t end up reading mountains of irrelevant data.
The one thing that you are missing is the Repository. Rather than introduce the complexity of data access I am simply using a static Dictionary to store the data:
That’s everything you need. Hope that you find this useful.
- I did not have an HTML form (the application I was working with is very “AJAX heavy”).
- I needed to pass parameters in addition to the file (the ID of the entity that I want to associate the file with).
Select File to Upload: <input id="file" name="file" type="file" />
<img id="fileView" />
<script type="text/javascript">
$(document).ready(function () {
$('#file').change(function () {
var data = { ID: "b53dd6b4-f24c-4450-bf6a-246e5835a125" };
$(this).upload(
"FileUpload/AttachFileToEntity",
data,
function () {
$("#fileView").attr("src", "FileUpload/GetFileDataFromEntity/" + data.ID);
}
);
});
});
</script>
- Uploads the selected file
- Displays it. I am assuming that you are uploading an image (but not verifying this)
public class FileUploadController : Controller
{
private readonly EntityRepository _entityRepository = new EntityRepository();
public ActionResult Get()
{
return View();
}
public ActionResult AttachFileToEntity(Guid ID, HttpPostedFileBase file)
{
var entity = _entityRepository.Get(ID);
entity.FileData = GetFileData(file);
return Content("File saved");
}
private byte[] GetFileData(HttpPostedFileBase file)
{
var length = file.ContentLength;
var fileContent = new byte[length];
file.InputStream.Read(fileContent, 0, length);
return fileContent;
}
public FileResult GetFileDataFromEntity(Guid ID)
{
return File(_entityRepository.Get(ID).FileData, "image");
}
}
public class Entity
{
public Guid ID { get; set; }
public byte[] FileData { get; set; }
}
public class EntityRepository
{
private static readonly IDictionary<Guid, Entity> _entities = new Dictionary<Guid, Entity>
{
{ new Guid("b53dd6b4-f24c-4450-bf6a-246e5835a125"), new Entity { ID = new Guid("b53dd6b4-f24c-4450-bf6a-246e5835a125") }}
};
public Entity Get(Guid ID)
{
return _entities[ID];
}
public void Save(Entity entity)
{
if (entity.ID == Guid.Empty) entity.ID = Guid.NewGuid();
if (_entities.ContainsKey(entity.ID)) _entities[entity.ID] = entity;
else _entities.Add(entity.ID, entity);
}
}


