Dear Browser Makers: Please fix <input type=”file” />

tldr: Browsers need better ways of handling large HTTP requests – possibly with an "upload monitor" (Scroll to the last paragraph for a little more)

I think that we’ve all come across this before: you go to a website, select a file to upload, hit “Submit” and then wait forever and hope that the file you’ve selected has actually made it to the server on the other side. Recently, while building an ASP.NET MVC application for a client, I decided that I wanted a better experience for my end users, especially since this application is to be externally hosted from the client, who is the primary user. As such, I didn’t want the client to be waiting and hoping that the documents and images that they are uploading are actually reaching the other side.

So, to get past this issue, my first idea was to turn to AJAX. Using JavaScript made sense as it meant that no 3rd-party plugins are required and that anyone with JavaScript disabled can still upload files (albeit with a worse interface – but anyone disabling JavaScript should expect that). Unfortunately, AJAX file uploaders appeared to be mediocre at best – they were inaccurate with percentage (if they showed a percentage), the interfaces were pretty poor and most didn’t support multiple file upload features (such as selecting multiple files in the open file dialog).

With a quick bit of searching, I found SWFUpload – which appeared to have all the features that I wanted: a nice interface, multiple file uploads and very customisable. Having implemented SWFUpload into my application, I hit a major bug. As it turns out, SWFUpload was built using Flash, and Flash (being the wonderful Adobe application it is) only sends cookies from Internet Explorer, if at all. This meant that the uploading component would not use the same session as Firefox, and so would be redirected to the "log in" page instead of uploading the file. The suggested fix from SWFUpload didn’t work (apart from the various security exploits it introduced) and implementing my own SessionIDManager (to permit session id’s in the query string) failed due to ASP.NET’s SQL Membership Provider storing additional Authentication data in a separate cookie.

Luckily enough, Silverlight supports sending the cookies from the browser it is hosted in. Hoping for a simple, drop-in solution I was (again) severely disappointed. The Silverlight component I had chosen (Silverlight Multi File Uploader), as well as many others, send the file in the body of the HTTP request (instead of putting it in a mulitpart/form-data encoded POST header) and chunked the upload. This was greatly frustrating as I wanted to put the uploaded file straight into the database, without placing it temporarily on the file system. After some hacking of the Silverlight component, I was able to strip out the chunking code, but attempting to have the request use mulitpart/form-data failed due to Silverlight’s unusual (but rather logical) way of doing HTTP Requests. Silverlight relies on the browser sending the request and completing its headers (such as Content-Length). However, the Content-Length header is put before the Content-Type and this causes IIS (and, most likely, every other webserver) to ignore the POST variables. In short, I couldn’t have the file uploaded properly (ie appearing in the Request.Files array), but I could live with put it in the HTTP Request body (and access it via the Request.InputStream stream).

But enough of the backstory – what is to be done? Well, its quite simple. The user’s browser should realise that it is uploading a large file and show the user how much of the file is complete (and, possibly, speed and estimated time). I find it curious that the user is presented so much information about a download and yet next to nothing about the statistics of an upload. When you think about it from a web developer’s point of view, the browser is the only place to implement this feature. Why? Because HTML is for content, CSS for styling and JavaScript for functionality. Out of those three, JavaScript is the best candidate for implementing an upload "monitor"; but JavaScript has no information about the OS the browser is in (nor should it), and so there is no way for the JavaScript to know how large the file is – this means that the responsibility falls out of the Web Developer’s hands and into the browsers hands.

Tagged , , , ,

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: