ASP.NET MVC Application Building: Family Video Website #5 – Multiple File Upload with Progress
In this series of tutorials, I build an entire ASP.NET MVC application from start to finish. In this entry, I add a Silverlight file upload control to make it easier to upload multiple media files.
This blog entry is part of a series of entries on using ASP.NET MVC to build an entire Family Video Website from scratch. Before reading this entry, you might want to read the previous four entries:
Family Video Website #1 – Upload the Videos – In this entry, I create an MVC controller that accepts large file uploads.
Family Video Website #2 –Add the Database – In this entry, I added a database so that I could associate additional information, such as a title and description, with each video.
Family Video Website #3 – Play Videos with Silverlight – In this entry, I added the ASP.NET MediaPlayer Silverlight player to the application.
Family Video Website #4 – Paging, Silverlight, and Flip – In this entry, I add paging to the application and demonstrate how you can encode and upload videos recorded with a Flip video camera.
Accepting File Uploads
The standard HTML <input type=”file” /> element does not work well when you need to upload large files (see Figure 1). It doesn’t display a progress bar. When you initiate the upload, your browser freezes. You have no idea whether something is happening or not.
The standard HTML <input type=”file” /> element also does not provide you with a method of uploading multiple files at once. Typically, I dump a large number of pictures from my camera onto my hard drive and I want to upload several of these pictures to the Family website. The standard HTML file upload element forces you to upload the files, laboriously, one at a time.
Figure 1 – The standard HTML file upload element
For these reasons, I decided to investigate alternatives to the standard HTML file upload element. I investigated both Ajax and Silverlight solutions.
Using Ajax for File Uploads
My first inclination was to implement an Ajax solution for accepting file uploads. Using Ajax, you can continuously poll the server from the browser to check on the progress of uploading a file. In that way, you can display a progress bar.
I found good reviews of different Ajax file upload solutions for ASP.NET in Matt Berseth’s blog and Jon Galloway’s blog at the following addresses:
http://mattberseth.com/blog/2008/07/aspnet_file_upload_with_realti_1.html
http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx
After reading Matt Berseth’s positive review of two open source Ajax file upload components, named NeatUpload and the ASP.Net File Upload/Download Module, I experimented with using these components in an ASP.NET MVC application. You can download these components from the following URLs:
http://www.brettle.com/neatupload
http://darrenjohnstone.net/2008/07/15/aspnet-file-upload-module-version-2-beta-1/
I made some progress in adapting these components to work in the context of an ASP.NET MVC application. However, after reading Jon Galloway’s blog, I decided to investigate a Silverlight solution to the problem of accepting file uploads.
Using Silverlight for File Uploads
When I need an answer to a Silverlight question, I turn to either Tim Heuer or Jesse Liberty who are the Silverlight gurus on my team. Tim recommended that I look into the following two Silverlight controls:
http://sandbox.inetsolution.com/fileuploadwebsite/FileUploaderTestPage.aspx
Both of these Silverlight controls enable you to upload multiple files. However, the first control is commercial and the second control is open source (the author says that the control will be released as open source with the Silverlight 2.0 release). Therefore, I decided to use the second control, the Multi File Uploader control, for the Family Videos Website application.
The Multi File Uploader is made of two parts. The user interface for accepting a file upload is created with a Silverlight control. You display the file upload user interface by adding a Silverlight control named mpost.SilverlightMultiFileUpload.xap to your project.
The Silverlight control is embedded in the Create.aspx view in Listing 1. The Create view enables you to upload new videos or pictures to the Family Video Website (see Figure 2). You can use the upload control to upload multiple pictures or videos at the same time.
Figure 2 – Using the Multi File Uploader Silverlight control
Listing 1 – Views\Media\Create.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeBehind="Create.aspx.vb" Inherits="FamilyVideos.Create" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Add New Media</title> </head> <body> <div> <h1>Upload Media</h1> <%-- MaxFileSizeKB: Maximum file size in KBs. <br /> MaxUploads: Maximum number of simultaneous uploads <br /> FileFilter: File filter, for example ony jpeg use: FileFilter=Jpeg (*.jpg) |*.jpg <br /> CustomParam: Your custom parameter, anything here will be available in the WCF webservice <br /> --%> <div id="silverlightControlHost"> <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="500" height="260"> <param name="source" value="/mpost.SilverlightMultiFileUpload.xap"/> <param name="initParams" value="MaxFileSizeKB=50000,MaxUploads=2,FileFilter=,CustomParam=yourparameters" /> <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/> </a> </object> </div> <a href="/Home/Index">Finished Uploading</a> </div> </body> </html>
The Silverlight control is embedded in the Create.aspx view with the help of an HTML <object> tag. The <object> tag includes a source parameter that points to the mpost.SilverlightMultiFileUpload.xap file in the project.
Notice that the <object> tag also contains an initParams parameter. You can use this parameter to configure several options for the Multi File Uploader control such as the maximum allowable size of an uploaded file.
The second part of the Multi File Uploader control is a WCF service. The Silverlight control calls the WCF service to pass the file being uploaded from the browser to the web server.
In order to use the service, you must add a reference to your project to the mpost.FileUploadServiceLibrary.dll assembly. This assembly contains a base WCF service that you can use as the base class for your WCF service.
The WCF service used by the Family Videos application is contained in Listing 2 and the code-behind class for this service is contained in Listing 3.
Listing 2 – SilverlightUploadService.svc
<%@ ServiceHost Language="VB" Debug="true" Service="FamilyVideos.SilverlightUploadService" CodeBehind="SilverlightUploadService.svc.vb" %>
Listing 3 – SilverlightUploadService.svc.vb
Imports System.IO Imports System.Web.Hosting Public Class SilverlightUploadService Inherits mpost.FileUploadServiceLibrary.UploadService Protected Overrides Sub FinishedFileUpload(ByVal fileName As String, ByVal parameters As String) ' Create new media object Dim newMedia As New Media() newMedia.Title = "New Media" newMedia.FileName = fileName newMedia.Description = "No Description" newMedia.EntryDate = DateTime.Now ' Add new media object to database Dim repository As New MediaRepository() repository.Insert(newMedia) ' Rename file Dim oldName = GetFullPath(fileName) Dim newName = GetFullPath(newMedia.MediaName) File.Move(oldName, newName) End Sub Protected Overrides Function GetUploadFolder() As String Return Globals.UploadPath End Function Private Function GetFullPath(ByVal fileName As String) As String Return HostingEnvironment.ApplicationPhysicalPath + "/" + GetUploadFolder() + "/" + fileName End Function End Class
When you create a service to use with the Multi File Uploader control, you override two methods of the base UploadService class. You override both the GetUploadFolder() and FinishedFileUpload() methods.
The GetUploadFolder() method returns the path to the folder where the file is uploaded. The FinishedFileUpload() method is called after the file is finished uploading. In Listing 3, the FinishedFileUpload() method is used to add a new Media item to the database that represents a newly uploaded file.
Finally, in order to get the Multi File Uploader control to work, you must add configuration information to your web configuration (web.config) file for the WCF service. The Family Videos application uses the system.serviceModel configuration section in Listing 4.
Listing 4 – web.config
<system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> <behaviors> <serviceBehaviors> <behavior name="FamilyVideos.SilverlightUploadServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="FamilyVideos.SilverlightUploadServiceBehavior" name="FamilyVideos.SilverlightUploadService"> <endpoint address="" binding="basicHttpBinding" contract="mpost.FileUploadServiceLibrary.IUploadService"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> </system.serviceModel>
The Multi File Uploader works quite nicely with Firefox (see Figure 3). This means that the Family Video Website works great with both Internet Explorer and Firefox.
Figure 3 – Multi file Uploader used in Firefox
Summary
I’m very happy with the new method of uploading files described in this blog entry. The Silverlight control solution solves both of the problems associated with the standard HTML file upload element discussed in the beginning of this blog entry. First, the Silverlight control provides you with visual feedback on the progress of a file being uploaded. Second, it enables you to efficiently upload multiple files at a time (for example, all of the pictures that you dump to your hard drive from your digital camera).
There is still more work to do on the Family Videos Website. For example, we still need to tackle missing pieces of the application such as form validation and authentication.