Restricting uploads to certain file types using Uploadifive

I was tasked with making a multiple file-upload form work in iOS browsers. The current solution leveraged Uploadify, a jQuery plugin which utilizes Flash to allow multiple file uploads simultaneously. A newer version of the plugin is available, called Uploadifive, which is a decent HTML5-based file-uploading plugin. HTML5 natively allows simultaneous file uploads, but for UI consistency, I employed the new plugin to handle modern browsers.

Problem

I needed users to only be allowed to select and upload .jpg, .jpeg, .png, and .gif files. In other words, I wanted the file types on the “safe” list to be the only files a user can select to add to the upload queue. Uploadifive seemingly has a fileType option for this, but with a vague docs entry. The example given restricts the user to one file type and tersely suggests how to restrict to more than one.

Findings

The docs suggest using an image string as an option, which will only upload images. They go on to say you can specify which type of image, giving an example of images/png (presumably a MIME type).

This worked, however the user is allowed to upload any type of file and will receive an error if the type chosen was wrong. Well that won’t work.

I next tried using a comma-delimited string, which is the format for the Flash-based option, in hopes that the functionality is similar.

Nope. I was still able to upload any file I wanted, but got an error for all files I selected, even the ones on the “safe” list.

Reading on, the option docs say:

…will also accept a JSON array to allow a specific set of fileTypes.

This behaves in the same way as the previous attempt; “Forbidden File Type” error for all files selected.

For kicks, I tried a normal array.

Unexpectedly, this does work, but in the same way as using a string (allow all to be selected, only allow “safe” list files to be uploaded). Frustrated, I reached out to the developer.

While waiting for a response, I copied the minified plugin into a JavaScript beautifier so I could reverse-engineer it. I found where the fileType option was being processed and threw in some console logs to see what data was being returned*. It turns out the option looks for a standard array (not a JSON array, as the docs state). As soon as a file is selected and added to the upload queue, the plugin will loop through the array of allowed file types, comparing it against the type of the file that was uploaded. If there’s a match, the file is allowed to be uploaded to the specified directory upon the form’s submission. Otherwise, a FORBIDDEN_FILE_TYPE error is thrown and the file cannot be uploaded, even though it remains in the queue.

While this functionality does work, it doesn’t offer the best user experience. Users can choose any file type and will get feedback if that file type is not allowed rather than having the ability to choose only the allowed file types. It’s confusing and it’s not the same experience as the Flash-based version of the same plugin.

* I didn’t include a Gist of this code because Uploadifive is a premium plugin.

Do It Yourself

HTML5 introduces a variety of new features to form inputs, including the accept attribute of the file input element. Using this, I can specify exactly which file types I want the user to choose from.

Authors are encouraged to specify both any MIME types and any corresponding extensions when looking for data in a specific format.

Because the plugin doesn’t afford the functionality that I’m looking for, I ignored the plugin’s fileType option and added my own jQuery script after the plugin instantiation, explicitly specifying which file types I want the form to accept.

Success! Now when I go to choose a file, only the allowed file types are selectable. Every other file type is grayed out and cannot be selected.

Conclusion

I have no negative opinion of the Uploadifive plugin. Technologies iterate fast and it can be hard to keep track of every available option – I get that. Not every plugin is perfect, not all documentation is sound. I thought I was missing something fairly obvious, but with a little research and some trial and error, I was able to work around the roadblock and come up with my own solution. Hopefully someone else experiencing the same trouble I had will stumble upon this solution and find it useful.

Update

The Uploadifive developer, RonnieSan, got back to me and it turns out he was unaware of the accept attribute. I forwarded him this post and he has since updated the plugin.