Introduction
It is difficult to find a decent upload control that handles large files, shows a progress bar, and still works in a medium-trust hosting environment. The problem with these controls is that medium-trust does not allow Reflection. But this does not mean that we are out of luck. One of the problems these controls strive to overcome is the server running out of memory when large files are uploaded by streaming the uploaded file to disk. But the HttpPostedFile
class description states that "By default, all requests, including form fields and uploaded files, larger than 256 KB are buffered to disk, rather than held in server memory." So, we don't have to worry about this problem. The other issue is feedback to the user by way of progress bar. Enter Flash's fileReference
API, which allows you to upload a file from Flash, and also keep track of it. FileReferenceList
allows the user to select multiple files.
Using the Code
Please read the article and the comments in the source code before asking questions in the forums.
I have finally gotten around to updating the Flash component of this article. I have re-written it using Flex, and have tried to add some of the suggestions from the message board. Some of the new features include adding files without clearing previously added files, removing individual files, individual progress bar as well as total progress bar, cancelling and then uploading does not re-upload previously uploaded files, ability to add and remove files while uploading files. The code is written using code behind and should be easier to modify. Moreover, all you need to make changes is a text editor and then you can compile it using the Flex 2 SDK, which is a free download from Adobe. Error handling should be better as well, though additional code may need to be added to handle it better. I have left the old fileUpload.swf and fileUpload.fla file in the source code in case anyone still wanted it. The source for the new FlashFileUpload.swf is contained in the FlashFileUpload_src.zip file and contains five files:
- FlashFileUpload.mxml - Main application GUI
- components\ApplicationClass.as - Main application code behind
- components\FileUpload.as -
FileUpload
class used for individual file uploading
- components\FileUploadEvent.as - A custom event class
- components\FileUploadProgressChangedEvent.as - A custom event class
I won't put the file's code in the article, you can download it and read the comments in the code. Also, a small declaration: I have little ActionScript experience, only from the first upload control and this one. Neither do I have any Flex experience. This is the first time I have looked at Flex. So if I did something in the code that is not best practice, or if it could have been done better another way, it is due to my inexperience with Flex and ActionScript and the small amount of time I put into writing it. I give no guarantees for this control. I hope you find this article helpful.
The code isn't very complicated, and is pretty well commented. I have now encapsulated the Flash object generation into a server control and embedded the FlashFileUpload.swf file in the DLL. See the comments in Default.aspx in the UploadPage folder for options and usage. I've included options to limit the file types to upload as well as limiting individual file size and total file size and can all be set using the server control. Also, setting the upload page, query parameters, and the JavaScript function called when completed are easily set using the server control.
I have included a number of examples for doing things with the upload control. This includes using a HttpHandler
as the upload page (lighter than using an ASPX page), using forms based authentication, and using sessions. I'll go over each real quick here, but will refer you to the source code for the actual code.
The uploading of the files are done using Flash (FlashFileUpload.swf) and can be used in any server side language, such as PHP, Java, Coldfusion, ASP, etc. If it can handle file uploads, it can use the Flash control. What the source code goes over is how to use it in ASP.NET.
The first step in using it in ASP.NET is to add the server control to a Web form (see UploadPage/Default.aspx) and setting the upload page in the server control's properties. The upload page can be any page that can handle uploaded pages, even another ASPX page. The preferred method is to use a HttpHandler
because it is lighter than an ASPX page. For an HttpHandler
, all that is required is a class that implements IHttpHandler
and some settings in the <httpHandlers>
section of the web.config. Also setting the maxRequestLength
in the <httpRuntime />
section would also be a good idea since this limits the size of file that can be uploaded to the server. The default is something like 2 or 4 megabytes. So you want to set this to the maximum allowed file size you want uploaded. That is all that is needed to use the upload control. The rest of the code is for the examples stated above.
Cookies and Flash
There is a bug in Flash and non-Internet Explorer browsers. From what I have read, Flash does not send cookies that were set in the browser with the uploaded file. This means that anything that uses cookies will not be accessible in the upload page. This means that sessions and forms authentication break using their default implementation, because they use cookies. This usually results in the dreaded #2038 error. There are some workarounds.
Forms Authentication
To get around the Flash bug problem using forms authentication, create a folder and add a Web form to the folder. This will be the upload page so add the upload control. Add a web.config file marking the folder accessible to anonymous users. Then in the page load of the Web form, check if the user is authenticated, sending them to the login page if they aren't. Then use the following code to encode the users identity ticket and put it in the query parameters of the upload control:
FormsIdentity cIdentity = User.Identity as FormsIdentity;
string encryptString = FormsAuthentication.Encrypt(cIdentity.Ticket);
flashUpload.QueryParameters = string.Format("User={0}", encryptString);
Then in the upload page, the identity can be extracted:
string EncryptString = context.Request.QueryString["User"];
FormsAuthenticationTicket UserTicket = FormsAuthentication.Decrypt(EncryptString);
And we can check if it is expired, or even get the user's username
:
if(!UserTicket.Expired)
{
string username = UserTicket.Name;
}
Sessions
Unfortunately sessions aren't quite as clean. In order to use them, sessions must be set to be cookieless. Doing this adds some gibberish to the URL. Usually it is transparent to the user. Set it in the web.config:
<sessionState cookieless="UseUri" />
If using an HttpHandler
, it needs to implement IRequiresSessionState
as well.
Quick Note
The source code solution was built using Visual Studio 2008, but is .NET 2.0 based. If you do not have Visual Studio 2008 (not sure if the free Web developer studio can open the solution or not), you can still open the Web project under FlashUpload_Web in Visual Studio 2005 or the free Web developers by going to 'File' and selecting 'Open Web Site' and browsing to the FlashUpload_Web folder.
History
- 09.28.2006 -- Initial post
- 07.10.2008 -- Source updated