Working with HTML5's multiple file upload support

This post is more than 2 years old.

This won't be a terribly long post, nor one that is probably informative to a lot of people, but I finally got around to looking at the HTML5 specification for multiple file uploads (by that I mean allowing a user to pick multiple files from one file form field). I knew it existed I just never got around to actually looking at it. Turns out it is incredibly simple.

You take a file form field:

<input type="file" name="myfile">

And you add multiple to it (or multiple="multiple").

<input type="file" name="myfiles" multiple="multiple">

And... yeah, that's it. Even better, it degrades perfectly. So in Chrome it works, and your label switches from...

to...

I kept waiting for the "But, wait" moment and it never came. In IE where it fails to work, it simply remains a file upload control that works with one file, not many. Because it's so simple and fallback is so good, I can't see really bothering to use another solution, like a Flash uploader, but you could do a bit of massaging for it. So for example, consider if my form had the following label:

Multiple File: <input type="file" name="files" multiple="multiple"><br/>

In IE, the user won't be able to select multiple files. While not the end of the world, it kind of bugs me that the label may mislead the user into trying something they can't do. (And as we know, the user will blame us, not IE.) So what to do?

I did some basic research into how to use JavaScript to detect features. I found a few good examples that basically suggested creating a temporary DOM item like so:

var el = document.createElement("input");

But here's where I had issues. Most of the links I found discussed how to detect new HTML form types, like range for example. These techniques worked by setting the type on the new element to the type you want to test and then immediately checking to see if the type still has the same value. But what about attributes?

Turns out Dive Into HTML5 has a great article on this. When you have your DOM item, you can simply ask if the item exists. Here is an example:

function supportMultiple() { //do I support input type=file/multiple var el = document.createElement("input");

return ("multiple" in el);

}

So given that, I modified my mark up a bit. I changed the label in front of my form and hid the word "Multiple":

<span id="multipleFileLabel" style="display:none">Multiple </span>File: <input type="file" name="files" multiple="multiple"><br/>

I then added an init method to my body tag and used the following code:

function supportMultiple() { //do I support input type=file/multiple var el = document.createElement("input");

return ("multiple" in el);

}

function init() { if(supportMultiple()) { document.querySelector("#multipleFileLabel").setAttribute("style",""); } }

And that worked like a charm. IE say just "File" whereas Chrome and Firefox had the new hotness.

So yeah - that's a lot of writing about a simple little thing, but... dare I say it... I'm really getting jazzed up about HTML again!

Here's my entire test template if you want to cut and paste:

<!DOCTYPE html> <html> <head>

<script> function supportMultiple() { //do I support input type=file/multiple var el = document.createElement("input");

	return ("multiple" in el);
}

function init() {
	if(supportMultiple()) {
		document.querySelector("#multipleFileLabel").setAttribute("style","");
	}
}

</script> </head>

<body onload="init()">

&lt;form action="" method="post" enctype="multipart/form-data"&gt;
Normal Text: &lt;input type="text" name="name"&gt;&lt;br/&gt;
&lt;span id="multipleFileLabel" style="display:none"&gt;Multiple &lt;/span&gt;File: &lt;input type="file" name="files" multiple="multiple"&gt;&lt;br/&gt;
&lt;input type="submit"&gt;
&lt;/form&gt;

</body> </html>

p.s. So how you actually process the upload depends on your server. My ColdFusion readers are probably wondering how it handles this. Good news, bad news. The bad news is that ColdFusion can't (as far as I and other smarter peoiple know) handle this at all. If you want to do this in ColdFusion 9, use the Flash based multifile uploader instead. The good news is that ColdFusion 10 handles it just file. Be sure to use action value of "uploadall" of your cffile tag.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by GB posted on 2/29/2012 at 11:14 AM

It can! Coldfusion can handle it. I know because it's working for me. It's super simple too. I recently started looking into this as well.

<cffile action="uploadAll" ... />

There is also another solution. Using HTML5 ajax file upload you can essentially upload one file at a time but its threaded so they upload in parallel. You have to write the cfml on the server to put the files into a temporary location and log the uploads as only partially complete in a queue of some sort until the user submits the rest of the form and then you finish the process on the final submit which is quick because the files were already uploaded. That does get tricky because you should make an upload progress bar or indicator that the uploads are in progress but it's kinda fun learning it.

Comment 2 by Raymond Camden posted on 2/29/2012 at 4:30 PM

GB, I believe you are wrong. Did you actually test it? When run, if you have 3 files selected, it will copy them all to one particular file name. Trust me - I tried this. It does work if you have N file/form tags though.

As for an Ajax-file file upload - yeah - that does work - along with Flash solutions, but this blog post is specifically about the multiple attribute _only_.

Comment 3 by GB posted on 2/29/2012 at 9:32 PM

You're right, I was wrong. It only uploaded one file. I just tested it and only the last file added was uploaded.

I went back and looked at my previous test code to where where I was using the action="uploadAll" and I'm using it to process the ajax file upload. That's why the HTML5 ajax solution was on my mine. The UploadAll was the only way to upload a single file being send via ajax because there was no 'fieldname' being sent for Coldfusion to grab.

You *could* try grabbing the data content from GetHTTPRequestData() and parsing out the files using the header Content-Type boundary string, but that get hairy really quick. I thought I was going to have to do that until I tested the action="uploadall" to process the ajax upload. I'm glad it worked for that.

It's too bad the uploadAll doesn't work for HTML5 'multiple' files. These sort of issues make me want to dig into the java source code of Railo and see what and why. Maybe another day.

Comment 4 by Raymond Camden posted on 2/29/2012 at 10:17 PM

Actually, I disagree again. ;)

"That's why the HTML5 ajax solution was on my mine. The UploadAll was the only way to upload a single file being send via ajax because there was no 'fieldname' being sent for Coldfusion to grab."

If you use the CF9 Ajax multi file uploader, it actually sends ONE file at a time, and sends it like any other regular file. You use cffile/action=upload and just process it. Seriously - watch it with a network monitor. It fires off one file at a time.

cffile/action=uploadall is ONLY used (afaik), in cases where ONE network request contains N form field fields of type file. So even then it's just a convenience. You could still use N cffile/action=upload calls.

Comment 5 by Bryan posted on 3/26/2013 at 8:41 AM

"...In IE, the user won't be able to select multiple files..."

Yes, they can now, with IE 10.

Nice, informative article, by the way - thanks!

Comment 6 by Raymond Camden posted on 3/26/2013 at 2:05 PM

Nice. Thanks for testing this in IE10.

Comment 7 by shad posted on 9/21/2013 at 5:10 AM

is there a way to get the temp file name to php script using ajax.i tried using the xhr object but to no avail

Comment 8 by Raymond Camden posted on 9/21/2013 at 9:27 PM

I'm not quite sure I get what you are asking here. Can you rewrite the question?

Comment 9 by Chris Bowyer posted on 12/19/2013 at 1:29 AM

Very cool, however, after playing with this, I decided to just label as 'File/s', and place a message under the input, stating, "Please note that multiple file selection is not supported by Internet Explorer version 9 or less". One thing I would like to change though, is Chrome's button value, from 'Choose Files' to 'Choose File/s', or just plain 'Browse', and the wording beside it, from 'No file chosen' to 'No file/s chosen', or just get rid of it altogether.

Comment 10 by Raymond Camden posted on 12/19/2013 at 2:10 AM

I've seen web pages before where they bind an image to a file upload control.

Comment 11 by Chris Bowyer posted on 12/19/2013 at 2:23 AM

That's a good idea. Thanks!

In addition, any thoughts on unrestricted file type uploads, in particular, when they are just being deleted after being emailed, not when they can be downloaded. I don't see an issue.

Comment 12 by Raymond Camden posted on 12/19/2013 at 3:46 AM

Um, as long as you do not upload to a web accessible directory then it should be fine.

Comment 13 by Chris Bowyer posted on 12/19/2013 at 4:08 AM

Good point, and thanks again!

Comment 14 by Misty posted on 2/20/2014 at 12:10 PM

Hi ray,

itried the Code in Firefox and IE8, It failed in both cases, in Firefox, selecting multiple files, the dialog box of the files stays open.

in IE8, it just selects only one file. i can show the screenshots for this

regards

Comment 15 by Raymond Camden posted on 2/20/2014 at 4:48 PM

Multiple as an argument isn't supported in IE8 - so this is expected. It should just work as a single file upload control which is fine. What version of Firefox did you try?

Comment 16 by Timothy Jasko posted on 1/3/2016 at 3:17 AM

I know I'm late to the party here, but I figured out how to make CF handle multiple file uploads:

http://coldflint.blogspot.c...

Comment 17 (In reply to #16) by Raymond Camden posted on 1/3/2016 at 4:54 PM

Why not use cffile/action=uploadall? http://www.raymondcamden.co...

Comment 18 (In reply to #17) by Timothy Jasko posted on 1/5/2016 at 2:40 AM

uploadAll uploads every file that was submitted indiscriminately, without telling me which field it came from. My use case requires me to distinguish between the file upload fields. Basically, I have one field where they upload a file (sometimes a group of files) which the system parses and imports, and another field where they can upload an arbitrary number of documents which the system attaches but otherwise ignores. It's important for me to be able to distinguish between them.

Comment 19 (In reply to #18) by Raymond Camden posted on 1/5/2016 at 2:44 AM

Wow, really? I haven't used CF in a while, but that seems silly. Of course one can process the form upload manually.