Upload multiple files with a single file element

Published July 13th, 2005

STOP PRESS: There is now a new version here, based on Mootools.

Please note: As you will notice if you take the time to read this article, you will see no mention of the word ‘Ajax’ (apart from the ones in this paragraph). That’s because this technique has nothing whatsoever to do with Ajax — and I never claimed that it did. The fact that people are linking to this page and suggesting some sort of Ajax-y connection has nothing to do with me. So please, no more “but it’s not Ajax!” comments.

Thank you.

10th October 2005: Updated to add Safari support. Many thanks to Luis Torrefranca, Jamie Butler and Matt Kurpiewski (http://www.law.pitt.edu) and Shawn Parker & John Pennypacker (http://www.fuzzycoconut.com) for their help. Please download again.

2nd October 2005: I updated the script to fix a potentially nasty bug.

If you have a form where you want to allow a user to upload more than one file, you’re stuck with either adding as many file input elements as the number of files you want to upload, or possibly having new ones appear ‘magically’ through Javascript.

I was mulling over some ideas while walking home from work last week, when I came up with what I thought might be a quite cunning (and more atttractive and useable) way to allow a form to use a single file input element — sort of — to upload multiple files. Since you can only store file upload information in a file upload element (<input type=”file”>), you’ll always need to have one element per file to be uploaded. But what occurred to me is that you don’t need to display all those file elements.

Using the DOM, it’s actually a relatively simple matter to conceal a file element once a file has been chosen, and add a new (empty) one in its place. And to keep doing so, as many times as you like. It all happens so quickly, that it appears that there’s only one input element.

To make it even smarter, you can then read the value of each element (ie. the name of the file to be uploaded) and build a list, in whatever format you like, of chosen files. And with a little bit more code you can add the ability selectively to remove files that have been picked.

Enough waffling — here’s a demonstration:

Files (maximum 3):

I’ve deliberately left all styling out of the class, so the list is ugly (you can edit this yourself quite easily). And obviously there’s no submit button (I don’t want a load of junk files uploaded to my host, thanks) so I can’t show it ‘in action’ as such. You’ll just have to take my word for it, that it really does work. Or of course, download the (zipped) file and try it for yourself (don’t use the version included in this page, it’s slightly different).

The code is heavily commented to explain a) how to use it and b) how it works, although I’ve also included a compressed, comment- and whitespace-free version which is significantly smaller. I’ve tested it successfully with Mozilla Firefox 1.04, MSIE 6 and Opera 8 but I’m fairly confident that it’ll work with most, if not all, modern DOM-enabled browsers — if you can confirm or disprove this, please let me know.

One thing to be aware of when allowing mutliple uploads is that there are generally limits on the quantity of data that can be sent in any one request — for example, PHP has a default limit of 2MB (although this can be changed, using ini_set(’upload_max_filesize’, ‘[new size]M’) where new size is the maximum number in megabytes — this will not work if safe mode is enabled on your host).

If you’re looking for help handling the files once they’ve been uploaded, you could do worse than take a look at this this comment by Shawn Parker (thanks again, Shawn!).

The licence for this code is simple: use it how you like, but don’t blame me if it breaks anything. Also, it’d be nice if you’d leave the credit (with the link to this site) in the code.

Get a Trackback link

33 Trackbacks/Pingbacks

  1. Pingback: Tired Idea » Blog Archive » Upload. Wash. Rinse. Repeat. on August 17, 2005
  2. Trackback: geek ramblings on September 27, 2005
  3. Pingback: warpedvisions.org » Blog Archive » Ajax multi-file upload on September 28, 2005
  4. Pingback: Incoherent Babble » Blog Archive » Ajax Multi-Upload Utility on September 28, 2005
  5. Pingback: Kiss in the dark » Upload de fichiers multiples avec un seul champ file on September 28, 2005
  6. Trackback: InfoSauce on September 28, 2005
  7. Trackback: Fiftyfoureleven.com Web Development Weblog on September 29, 2005
  8. Trackback: Bluetrait on September 30, 2005
  9. Pingback: vasily kartashov » Blog Archive » Ссылки on October 4, 2005
  10. Pingback: PhotoStack » Beta 361 on October 4, 2005
  11. Pingback: A random pixel » Upload multiple files with a single file element on October 19, 2005
  12. Pingback: 今日連結 (2005-10-31) [JeffHung.Blog] on October 31, 2005
  13. Pingback: PhotoStack » r373 on November 3, 2005
  14. Pingback: h7 blog » Blog Archive » Mehrere Dateien uploaden on December 22, 2005
  15. Pingback: Bram.us » My TinyMCE File Management : Spinoff 1 : PHP file uploads on November 30, 2006
  16. Pingback: Subir archivos multiples al servidor con AJAX - SWFUpload at mi binxe blog :P on December 19, 2006
  17. Pingback: 15 Days Of jQuery : Multiple File Upload Magic With Unobtrusive Javascript on December 19, 2006
  18. Pingback: www.svetoslav.info » Blog Archive » Upload multiple files on February 24, 2007
  19. Pingback: It Forx on March 28, 2007
  20. Pingback: Urls Sinistras » Blog Archive » del.icio.us entre 27/04/2007 e 02/05/2007 on May 3, 2007
  21. Pingback: Mai 07/02 on May 13, 2007
  22. Pingback: Upload multiple files with a single file element « Brave Dave’s Musings on May 31, 2007
  23. Pingback: Multiple file uploader: Mootools version » StickBlog on July 2, 2007
  24. Pingback: ???? (2007-07-04) [JeffHung.Blog] on July 6, 2007
  25. Pingback: omeck - strona domowa » Archiwum » Upload wielu plików na serwer w CakePHP v1.2 on July 19, 2007
  26. Pingback: jacobslusser.com » Blog Archive » Multiple File Upload on September 13, 2007
  27. Pingback: Upload de múltiplos arquivos usando um único INPUT. « Trecos & Tarecos da Informática on December 28, 2007
  28. Pingback: gauda.de » Blog Archive » Multiple File Upload with Ruby on Rails and file_column on January 21, 2008
  29. Pingback: M.I.S.H.U. » Blog Archive » Cakephp: working multiple files uploads ready to download script on February 7, 2008
  30. Pingback: PHP File Upload « ??????? on April 16, 2008
  31. Pingback: Multiple file uploader: Mootools version | Stickblog on July 21, 2008
  32. Pingback: Multiple file uploader: Mootools version | Stickblog on July 21, 2008
  33. Pingback: Multiple file uploader: Mootools 1.2 version | Stickblog on July 21, 2008

394 Comments

  1. nate on August 19, 2005

    Thanks for your code! I think there might be a bug in multifile.js, though. When I first tried it, I was having problems that the file input was immediately disabled after I intialized MultiSelector. Problem seemed to be with:
    if( this.count >= this.max || !this.max ){
    element.disabled = true;
    };
    If max is ‘0′ (no limit), (! this.max) is true, and the element is disabled before it is used. I think you want “if (this.max > 0 && this.count >= this.max)” or the like.

  2. Stickman on August 25, 2005

    Thanks for the bug report — you’re absoultely right. I’ve changed the code such that if max isn’t specified, it’s set to -1. The code then checks for this value when verifying the maximum number of files.

  3. Thuven on September 12, 2005

    Hi dude. thanks a lot for the helping hand .. you rock!! …

  4. Le on September 14, 2005

    Hi dude, thanks a lot for the script… :).

  5. Dougal Campbell on September 27, 2005

    If you have javascript disabled, you get one file input, but it still says “maximum 3″. You might want to either generate the “maximum” message via JS, or perhaps fall back to displaying all of the file inputs when there’s no scripting. You could default to displaying them all, and hide the extras with JS when it’s available.

  6. Mark Wubben on September 29, 2005

    There’s a memory leak in the code though. (Circular reference through closures leads to memory leaks in IE.) To fix it, set the `list_target` and `element` variables to null once you’ve set all the events.

    More here: http://novemberborn.net/javascript/event-cache

  7. sean on September 29, 2005

    Nice! On several of the sites I run, I just have 10 file upload boxes so you can choose to upload up to 10 files at a time (pics mainly), and I always thought it looked like hell. This will make it a lot better :D

  8. legionnewbie on September 29, 2005

    Dont suppose anyone would want to help out a newbie. How do I

    3. Instantiate a MultiSelector object, passing in the DIV and an (optional) maximum number of files
    * eg. var multi_selector = new MultiSelector( document.getElementById( ‘files_list’ ), 3 );
    Where do I put this ? in the _js file or the html file.

    sorry for the newbiness

  9. neal on September 29, 2005

    Just a thought, but how does it handle the case when three files have been selected and the first one is then deleted and another one added?

    I only ask as looking at the code it appears you will get two input elements with the same name.

  10. Kae Verens on September 30, 2005

    The demo does not work in Konqueror. I have not checked the source, though, to see what was wrong, but I’m sure it is easy to fix. If I fix it before you do, then I’ll alert you with the code changes.

  11. Touxe on September 30, 2005

    Thanks a lot for this very useful multi upload form.
    I’d like to change the “list-file” output for a table.
    In the first cell, the filename and in the second the button. I would like to do this in order to have all filename and button align.
    I’have tried but i’m a newbie. I’m able to create new line in my table but i can’t delete it.

    Can someone help me … thanks a lot.

    ps : sorry if you don’t understand me :)

  12. ceejayoz on October 1, 2005

    That is a beautiful approach! Wow!

  13. Dustin Diaz on October 1, 2005

    What a brilliant idea!
    Simple, Elegant, well documented and fast. The source is easy to follow and had no problems iterating through the logic. well done.
    Next time I run into a case where I need to upload multiple files, I’ll remember to keep this in mind.

  14. Jose on October 1, 2005

    Hi, i don’t know what am i doing wrong, all i get is a “Error: element has no properties” Javascript error and a think i followed all the instructions given.

    Does anyone have the same error?

  15. Stickman on October 2, 2005

    To everyone who’s linking to me, and for all the praise: thanks, I’m flattered. :)
    To everyone having problems getting this to work: I’ve added an example HTML file to the .zip.

    To neal: you’re right about the duplicate name problem, thanks for pointing it out. I’ve added a not-very-clever fix for the moment, until I get time to rewrite it properly.

    To Mark Wubben: I’m aware of IE’s memory leak problems but hadn’t really thought about them when writing this. When I get a moment I’ll look at rewriting to take this into account.

    To Kae Verens: I don’t have access to a machine running KDE to test on Konqueror. Any suggestions as to what the problem is (and potential solutions) are most welcome.

    I’m about to go on holiday for a week, so no more updates will occur until I get back.

  16. Jose on October 2, 2005

    Now is working great! Thanks man, awesome work!

  17. tdgraphix on October 2, 2005

    Great Idea and Implementation! Works like a charm!

  18. mattl on October 2, 2005

    Works in Safari too.

  19. Tom on October 2, 2005

    Nice but it has problems :-( On Mac OSX 10.4.2 it works fine with Firefox but does not perform any uploads (error: 4) when used in Safari (2.0.1) In my test file the first form using your sample fails but the second vanilla upload works fine. Any help would be appreciated.

    Tom

    “;
    print_r ($_POST);echo “”;
    ?>

    ” method = “post”>

    Files:

    var multi_selector = new MultiSelector( document.getElementById( ‘files_list’ ), 3 );

    multi_selector.addElement( document.getElementById( ‘my_file_element’ ) );

  20. Tom on October 2, 2005

    neal,

    why not just name the input something like “”userfile[]” and then deal with the php array in $_FILES on accepting the POST?

  21. Hans on October 3, 2005

    Nice work!
    It is annoying to have a script tag in the middle of the code. How about putting the entire script in one file? Then you need to add some more code. Note that the code that was previously in the script tag, is now in the _init code:

    addEvent(window, “load”, multiselector_init);

    function multiselector_init() {
    var multi_selector = new MultiSelector( document.getElementById( ‘files_list’ ), 3 );
    multi_selector.addElement( document.getElementById( ‘my_file_element’ ) );
    }
    function addEvent(elm, evType, fn, useCapture)
    // addEvent and removeEvent
    // cross-browser event handling for IE5+, NS6 and Mozilla
    // By Scott Andrew
    {
    if (elm.addEventListener){
    elm.addEventListener(evType, fn, useCapture);
    return true;
    } else if (elm.attachEvent){
    var r = elm.attachEvent(”on”+evType, fn);
    return r;
    } else {
    alert(”Handler could not be removed”);
    }
    }

  22. David Kaneda on October 3, 2005

    I can confirm the script doesn’t work in the most recent Safari-

  23. Adam on October 3, 2005

    Thanks man! I was thinking about the same thing the other day after work, with a quick Google, I found you. It’s good to know we don’t all have to do the work twice as long as there are plenty of people like us out there.

  24. Noel Jackson on October 4, 2005

    This is awesome. Mind if I use it in PhotoStack???

  25. Noel Jackson on October 4, 2005

    Well, I thought I would, but it doesn’t work in safari! DOH!

  26. Jim Johnson on October 4, 2005

    Just saying thatnk found the element I already had plus used your element.onchange=funtion rather than my addHandler()
    works cross browser better Appreciate the code

  27. delvinj on October 5, 2005

    Nice work. anyone tried this with a servlet or jsp on the recieving end?

    ~d

  28. Noel Jackson on October 5, 2005

    Anyone know how to get this working in Safari? I’d love it if you could tell me.

  29. Shawn on October 5, 2005

    I believe that it has something to do with assigning it a display of ‘none’ when created.
    CSS behavior will have an element like an image not even load from the server with a display: none; - and if you remove line 77 ( this.style.display = ‘none’; ) from the js file Safari works.

    There needs to be another way of hiding the newly created file input element. Maybe hiding a div that contains it instead of the element itself…

  30. Noel Jackson on October 5, 2005

    how about text-indent: -1000 em; ???

  31. Shawn on October 5, 2005

    Tried that and it didn’t like it. On top of that - whenever I did get something to work in Safari, Firefox would freak out and either show a sliver of the element or not work like Safari did…
    Granted, I’m not a CSS or Javascript Guru by any means - I’m still learning - but there just might have to be some browser sniffing going on here.
    A little browser sniffing could get this to work because every other browser responds to display: none being applied to the element while Safari liked having height: 0; width: 0; overflow: hidden; applied to it.
    I know its archaic to browser sniff, but for now its the only way I found to do it. I might also try putting a size limit on the list div and make sure it does not grow, and make sure the new file input elements don’t run inline but that they each run on a new line - that way overflow: hidden could be applied to their parent element without styling the inputs themselves.
    I didn’t have time to test that concept yet.

  32. Luis Torrefranca on October 6, 2005

    For a mailer, I added a browser sniffer and changed the style handling to this:

    if (is_safari) {
    this.style.position = ‘absolute’;
    this.style.left = “-10000px”;
    } else {
    this.style.display = ‘none’;
    }

    I was also having some trouble retrieving the data, so we modified the element.name to use an array:
    element.name = ‘attachment[]‘;

    and retrieved it on the php processing page with:
    $files = sizeof($_FILES['attachment']['name']);
    for ($i = 0; $i

  33. Luis Torrefranca on October 6, 2005

    oops… code cut me off…

    anyway, loop through from 0 through the array size. Then call them by:
    $_FILES['attachment']['tmp_name'][$i] and so on

    again, hope this helps

  34. superkain on October 6, 2005

    Looking Good man! Great inception.

  35. Shawn on October 7, 2005

    Luis - I just came back to post that same Safari fix - damn you! ; )

    I got around the files thing by just doing a foreach on the $FILES array and only working on the entries that had an error of 0. Saved the extra hassle of having to do it client side.

    Lets see if all my code makes it

    $no_files = 0;
    foreach($_FILES as $file)
    {
    switch($file['error'])
    {
    case 0:
    // file found
    if($file['name'] != NULL && okFileType($file['type']) != false)
    $v = processFile($file);

    // build string for confirmation display
    if(isset($v) && $v == true)
    {
    showSuccess($file);
    $no_files++;
    }
    break;

    case (1|2):
    // upload too large
    $error[] = ‘file upload is too large’;
    break;

    case 4:
    // no file uploaded
    break;

    case (6|7):
    // no temp folder or failed write - server config errors
    $error[] = ‘internal error - flog the webmaster’;
    break;
    }
    }

  36. Pranveer on October 7, 2005

    where is catch.php

  37. Shawn on October 7, 2005

    Another Safari fix: I changed my delete button into an image button, and for some reason after I did that Safari wanted to refresh the page after doing that which also cleared my upload fields.

    This can be avoided by simply adding:
    return false;
    to the end of
    new_row_button.onclick= function(){
    // Remove element from form
    this.parentNode.element.parentNode.removeChild( this.parentNode.element );
    // Remove this row from the list
    this.parentNode.parentNode.removeChild( this.parentNode );
    // Decrement counter
    this.parentNode.element.multi_selector.count–;
    // Re-enable input element (if it’s disabled)
    this.parentNode.element.multi_selector.current_element.disabled = false;

    return false; // add this to appease Safari
    };

  38. Leo on October 11, 2005

    What does this have to do with AJAX??? Does “AJAX” manicker now get used for any clever Javascript hack? Don’t get me wrong, I think the script is a cool idea, but it’s not AJAX unless it sends micro-requests to server in an XML format and does micro-updates of those responses.

    The whole point of AJAX is that I can send a request to server and update a part of the page without having to reload and re-render the whole page.

  39. Stickman on October 11, 2005

    You’re right, but then I never said it had anything to do with Ajax.

  40. smith288 on October 11, 2005

    AJAX is used very liberally these days. Its alot easier to say that than “asyncronis javascript connection without using xml…”

  41. Stickman on October 11, 2005

    True. But as has been pointed out, this widget is just DOM manipulation — there’s no client-server communication, unless you count the form submission (which is handled in the usual fashion).

  42. Sheetal Jain on October 12, 2005

    I have managed to get this working even by hiding the file control -Just the way Gmail does for email attachment -

    Had to dig through gmails’s dirty secert

    here is the solution

    http://

  43. Sheetal Jain on October 13, 2005

    Ops! - I didn’t put the url in last posting

    http://sheetaljain.blogspot.com/

    Thanks

  44. newbegin on October 13, 2005

    hello
    it good ….
    now i am plan to use this …

    Thanks

  45. Marcos Lopez on October 14, 2005

    It’s a wonderful solution, but…. what about having the ability to choose several files at the same time? or even all the files under a directory?

    It would be very usefule a “select folder” winamp-style control

    Thanx

  46. Stickman on October 14, 2005

    Not possible, I’m afraid. For very good security reasons, file input elements are very limited in their capabilities and there’s simply no way (that I’m aware of) to work around that.

    I suppose it’s possible that you could achieve it in Internet Explorer using a custom ActiveX control, but I’m no expert on that sort of thing and anyway, that would of course kill cross-browser comptability.

  47. MisterJ on October 18, 2005

    Excellent script !

    I have made a little mod in order to display only the filename i/o full path+filename :
    element_work = element.value;
    element_tab = element_work.split(”\\”);
    nbr_elements = element_tab.length;
    new_row.innerHTML = element_tab[nbr_elements-1];

    instead of :
    new_row.innerHTML = element.value;

    cheers ;)

  48. Jpep on October 19, 2005

    Can a javascript wiz please help me (if possible) change the delete button to the word ‘remove’. I’d rather use text instead of the button for style purposes. Thanks for the great work!

  49. Jpep on October 19, 2005

    Me again… Sorry, but I’m having a bit of trouble handling the multiple files using php. My original form was based on this example from php.net (http://us3.php.net/manual/en/features.file-upload.multiple.php). Here is my form…

    I then use the following php just to test the first upload on the first file.

    / $userfile is where the file went on the webserver
    $userfile = $_FILES['userfile']['tmp_name'][0];

    // $userfile_name is the original file name
    $userfile_name = $_FILES['userfile']['name'][0];

    // $userfile_size is the size in bytes
    $userfile_size = $_FILES['userfile']['size'][0];

    // $userfile_type is the mime type
    $userfile_type = $_FILES['userfile']['type'][0];

    // $user_file error is any error encountered
    $userfile_error = $_FILES['userfile']['error'][0];

    I echo these variables and the result is that I don’t get any data for the above variables. When I change the input id to id=”my_file_elementXXXXX”. The upload works. So obviously I’m doing something wrong on the php end.

    Any ideas? Thank you so much. Sorry for the multiple posts.

  50. Jpep on October 19, 2005

    Okay. I figured out what I was doing wrong. Obviously I cannot follow directions. If anyone else out there is having problems, make sure that your input field does not have a ‘name’ set. As per the instructions, make it look like this…

    Then one way (not the best way) of process the files with php would be the following…

    $file_count = sizeof($_FILES);
    echo ‘Number of files: ‘ . $file_count .’…’;

    for ($i=0; $i’;
    echo ‘Size: ‘ . $userfile_size.”;
    echo ‘Type: ‘ . $userfile_type .”;
    echo ‘Error: ‘ . $userfile_error .”;
    echo ”;

    }

  51. Jpep on October 19, 2005

    Oops. My code got cut off. What’s the best way to post php? Anyway, on the server (php), I use…

    $file_count = sizeof($_FILES);

    to get the number of files uploaded

    and then I just loop thru and process as needed using the file naming scheme provided by this script…

    $thisfilename = ‘file_’ . $i;
    $userfile = $_FILES[$thisfilename]['tmp_name'];

    Hope that helps someone out.

  52. Sudhir on October 19, 2005

    Hi

    I would like to use this script but I want to use the checkbox instead of delete button and I want to delete the checked files at once rather than deleting individually.

    Please help me in getting this if anyone has work around.

    Thanks in advance
    Sudhir

  53. Jpep on October 20, 2005

    ***Does not work in Netscape 7.02 / WinXP***
    Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02 (VAUSSU03)

    Yes, me again. I noticed that this demo doesn’t work in the above environment. In my test, I must hit the browse button again after selecting the file for the file to show in the file list below the form.

    In further tests, the files do not appear to upload either.

    Can anyone else confirm this behavior?

  54. Stickman on October 20, 2005

    I don’t have NS7 installed but I’ve tried it in NS8beta and it appears to work.

    If I could think of an elegant, reliable way (ie. not sniffing for specific browsers/versions) to exclude those browsers that are known to have problems, then I’d implement it. Suggestions welcome.

  55. hm on October 22, 2005

    doesnt do crap, just dumps me at http://localhost/your_script_here.script

  56. Stickman on October 22, 2005

    :) That’s the bit you do for yourself — hence the name ‘your_script_here’. If you need help handling the uploaded files, I suggest Google.

  57. Flyboy on October 24, 2005

    After uploading the files (done through ajax, so the uploadform never leaves the page) I want to reset the form so it’s ready to select a bunch of other files and then upload them too.

    But the submit button doesn’t react any more then.

    Is this a build in protection against people double clicking the button if they think nothing happend?
    And if so, how can I fix this so I don’t have to reload my whole page to upload another file.

    Thanks

  58. Stickman on October 24, 2005

    Interesting idea. You’d have to step through each element, using removeChild() to get rid of it. Or you could use innerHTML, but I wouldn’t recommend it.

    If I get a spare minute, I might create a clearElements() function.

  59. Flyboy on October 24, 2005

    ok, thanks

    now even reloading the form doesn’t help, because the javascript variables still exist on the main page.

  60. Javaholli on October 25, 2005

    Great thing! Thanks…
    I’ve made some changes for a nicer output (table).
    In the example HTML I replaced the tag with the following code:

    In the multifile.js file I’ve added/changed the following lines:
    var new_tr = document.createElement(”tr”);
    var new_td_filename = document.createElement(”td”);
    var new_td_button = document.createElement(”td”);
    // Set row value
    new_row.innerHTML = element.value;
    // Add button
    new_td_button.appendChild( new_row_button );
    new_td_filename.appendChild(new_row);
    new_tr.appendChild(new_td_filename);
    new_tr.appendChild(new_td_button);
    // Add it to the list
    this.list_target.appendChild( new_tr );

    Important thing is that the ’s are added to the tbody tag! It won’t work if you’re not using the tag. Took me a while to figure that out…

  61. dan on October 31, 2005

    how do i actually pass the value over to my asp page?

  62. Execute on October 31, 2005

    Hello, very nice code, isorta skim read the code after downloading, but i found this using AJAX search in google, obviously so did others who left angry comments :P.
    My question is, can you make an example of AJAX submitting the form? I have been having trouble submitting “file” inputs thru my AJAX script, I tried using the .value of the file input but it doesnt send it to the php script. How can i get the “Value” or the “file” itself with JS to send to PHP? any ideas?

  63. Stickman on October 31, 2005

    Execute: you can’t upload files via XMLHTTPRequest. Simple as that.

    However, as I think has been mentioned above you could use a hidden iframe. I’ve done it myself and it works, but it can be a bit of a pain to get it working reliably.

  64. Execute on October 31, 2005

    ok… yea i found that out after a little bit of reading afteri posted that comment. thats a shame… However I did use an iframe, and just did target=’iframe’, and it works out fine… but what do you mean “bit of a pain to get it working reliably”, was way easier than i thought. Is there something else you were thinking of?

    But still im amazed your script works in all these browsers, i havent tested with opera, or ie, but with firefox 1.07 works fine :). And i easily set it up without any hassle, so seriously great job, and i will include your comment etc and wont remove it ;P.

    Happy halloween from DesignPlanet.biz

  65. Stickman on November 1, 2005

    Thanks for the flattery — always appreciated :)
    For more info on the trials I had with uploading with iframes, see this entry.

  66. DisasterMan on November 1, 2005

    Found the script very easy to get working, and have used it to great effect. Thank you very much!

  67. vanaja on November 3, 2005

    Thanks for wonderful script.
    Can any one tell me how to create a space in between the path and button?
    i am new to programming.

  68. Emmerson Miranda on November 4, 2005

    Excelent work, It do all I need.

    Good luck!!!

  69. Robert on November 6, 2005

    This is very smart and cool.

    But….what is “Ajaxian” about this ?????
    I don’t see no XMLHttpRequest calls.

    Somebody please tell me

  70. Robert on November 7, 2005

    Re my comment above:
    Just want to clarify -
    STICKMAN did not call it AJAX in any way.

    I was referring to those other stupid blog posts calling it “AJAX” - fawking idiots

  71. Robert on November 7, 2005

    >>Flyboy Says:
    >> After uploading the files (done through ajax, so the upload

    hmmm you sure you did thru XMLHTTPRequest ?
    Care to share with us how you did it ?

  72. Execute on November 8, 2005

    Use iframes. because YOU CANT send files through javascript. I been lookin all over for a way to do it with the XMLhttpRequest rather than iframes. So you just simply target the iframe which is on top of your form, make it invisible with css and you got yourself a fake-ajax system :)

  73. Robert on November 8, 2005

    ^^^^ so “FlyBoy” is full of BS ?

  74. Stickman on November 8, 2005

    Calm down, Robert. Clearly, for some people, Ajax has become a catchall term for a variety of newer browser technologies. While that might not tie in with the strict meaning of the term as it was originally intended, I don’t think it’s necessary to be quite so pedantic about it.

  75. Fabian on November 9, 2005

    Heyho, just wanted to say thanks for this great Widget…
    It’ll help me in developing a FileBrowser-Servlet :)

  76. ahussam on November 10, 2005

    Hi, I am having some trouble with actually uploading the files in the backend, i tried a “stupid” approach to understand the logic, added 4 files, removed the 3rd the submit, used file_1 as static filename, then file_2…etc, it did not recognize file_2 although i removed the 3rd file !?

    also i need to know (as a concept) as I use CFML, how would I transform the number of files and the filenames to the backend, i know how to do that on 1 file, but i just can’t understand the logic here for multiple files

    thanks

  77. Tbolt on November 12, 2005

    Need to add a function that clears all onSubmit or whatever. Anyone set this up already? Otherwise you have to manually delete them out if you want to add more files.

    Otherwise, it’s a great little script.

    thanks

  78. Shawn on November 12, 2005

    For those still needing a file upload script - I offer up a starting point.
    Yes, a starting point. This script solely handles file uploads and nothing else. You are responsible for securing your user’s input - I simply can’t do that for you, nor can anyone else.

    http://www.top-frog.com/files/scripts/upload_sample.phps

    Feel free to use the script or modify it in any way. For more information on handling file uploads in PHP you can refer to these pages:
    http://us2.php.net/manual/en/features.file-upload.php
    http://us2.php.net/manual/en/security.variables.php

  79. JD on November 13, 2005

    Great tool….this is the simplest multi-upload tool that I have seen.

    I have a question…Is it possible to retrieve the number of file elements on the page at any given time? I am trying to send the “file count” in a hidden form field so that I know how many files to process on the server side.

    Any help is appreciated.

    Thanks for the work Stickman…….

  80. Ulrich Fuchs on November 14, 2005

    Hello!
    I copied the 2 script files in /catalog/, and inserted your code in my contact form.
    When I change input type to “image”, then I get an error - if I let it be as “file”, I can see the dialog, select pictures, but they will not be attached to the mail!!
    Please help me and explain what to change if I want that IPG and PNG pictures can be attached - but no DOC, PPS and such stuff.
    Thanks!

  81. prince on November 14, 2005

    ur script seems to be very useful…Stickman……can u make an image preview for uploading images.then it would be much useful.and also validate the image dimension,image type,etc….like the following one:

    http://www.reallycoolspace.com/upload.html
    http://www.reallycoolspace.com/upload.js (the js file, the html file links to this)

    but this script doesnt work in all browsers.plz rectify it thru ur script….

  82. Flyboy on November 15, 2005

    Just back from a holiday and euhm, no, I’m not full of BS
    You surely can upload files through javascript.
    Problem is I wanted a status bar with it, had no time to do it all in ajax, so now I ended using 1 iframe, just for the status bar, will try and change that shortly too.

    Now my only need is the function to clear out all the variables instead of having to do it manualy every time.

  83. David Levin on November 15, 2005

    Awesome tool! Great work!

  84. Magic on November 15, 2005

    Hi all. i tried that script at firefox 1.0.7. it does not works. it upload only one file. other selected files not uploads.

  85. dpinto on November 16, 2005

    Can you add a feature that checks if the same file is added twice in the list and alerts the user that he already has added that file once.
    Overall its a nice script.

  86. dpinto on November 16, 2005

    Also that delete button could be an HTML link.

  87. dheeraj on November 23, 2005

    hi,
    Thanks for your usefull code for multiple file upload…but I need that the file dialog box must be hidden… and instead of it their should be a link “upload files” just like GMail file attachment.
    I have tried it but i have to click submit button 2 times to submit the files..
    Pls give me a solution for that..

  88. Mitt on November 23, 2005

    First off, great job! Second for those of you who have asked about the image preview, I wanted the same thing but found that Firefox will not allow the image preview to work because it is a security feature to disallow linking or access to local files. I was able to make it work in IE but ened up leaving it out all together because I don’t like to restrict users on a browser they have to use.

  89. Scaramouch on November 25, 2005

    First off, great script. You’ve “thunk” outside the box a bit & come up with what i think is a very good approach to this. Now if i can only figure out how to use is in a .NET environment.

    Does anyone know how i might be able to grab the files once they’ve been uploaded? Typically, i’d use the <asp:FileUpload> control, or even just something like <input type=”file” id=”file_1″ runat=”server”> (note the runat=”server” property) so that the control can be referenced server-side by it’s id. However since the file elements are being added client-side this approach won’t work.

    I’d love to be able to use this script in my webform if I can.

    Any help would be appreciated. Thanks.

  90. Stewart Boutcher on November 26, 2005

    I can verify that this script does not work in Firefox 1.0.7, either with file input naming convention “file_0″, etc or with “userfile[]“. In all cases only the first file is ever uploaded.

  91. Mir Ai on November 28, 2005

    Hi Everyone,

    Very, very cool solution to uploading multiple files.

    My requirements are a little different. I don’t want the user to see the file input files (text field or browse button). I want to be able to show a link which says “Add File”. I’ve tried hiding the ‘my_file_element’ field and then adding a link on the page which calls the following method:

    // adds a new file
    function addFile() {
    var myUploadField = document.getElementById(’my_file_element’);
    if (myUploadField != null) {
    myUploadField.click();
    }
    }

    This “sort of” works. Clicking the links adds the file and then shows the uploaded file name in the list. However, it adds more file upload fields to the screen and when I try to remove an uploaded file, it gives me a javascript error. The form also does not want to submit the first time. I have to click the submit button a second time.

    Any ideas or thoughts on how to make this work?

    Thanks,
    Mir

  92. Shawn on November 28, 2005

    Well, the script works fine with Firefox 1.0.7 on Mac. So I’d venture to guess that there is something wrong with the usage for the complaint that it doesn’t work on FF 1.0.7

  93. ®@T@Ø on November 28, 2005

    How I can restrict the type (s) of archives for upload?
    In the javascript, not in PHP. Something of this type was thinking about using substr to only catch the extention of the value of input file, but I did not obtain…

    Sorry my english, I´m brazilian…

    I´m waiting a return!!!

    ;º)

  94. Joe Shelby on December 3, 2005

    It works fine for me on Firefox 1.0.7 for Windows and IE 6, using JBoss/Tomcat/Struts/LazyDynaBean for the server side.

    I hacked at it a bit. We needed to associate a description with the file as part of the app i’m using it in, so I added a callback feature along with some additional references. diffs are bolded below:

    function MultiSelector( list_target, max, handler ){

    // Is there a maximum?
    if( max ){
    this.max = max;
    } else {
    this.max = -1;
    };
    // Is there a callback?
    this.callback = handler;

    element.onchange(): add the new if
    // Hide this: we can’t use display:none because Safari doesn’t like it
    this.style.position = ‘absolute’;
    this.style.left = ‘-1000px’;

    if (this.multi_selector.callback) {
    this.multi_selector.callback(this, “added”);
    }

    };

    this.addListRow(): add new_row as a reference so callback can manipulate it.
    // References
    new_row.element = element;
    element.new_row = new_row;

    a demo callback:
    function additionalAttachmentsCallback( element, action ){
    if (action == ‘added’) {
    element.new_row.appendChild(document.createElement( ‘br’ ));
    var t = document.createTextNode(”Description:”);
    var new_row_description = document.createElement( ‘input’ );
    new_row_description.type = ‘text’;
    new_row_description.value = ”;
    new_row_description.size = 60;
    new_row_description.name = “desc_” + element.name;

    element.new_row.appendChild(t);
    element.new_row.appendChild(new_row_description);
    }
    }

    and now in addition to getting file_0, my struts action can look for a desc_file_0 for the description.

  95. Wing on December 7, 2005

    This isn’t an example of AJAX. It’s just manipulating the DOM using Java.
    Where’s the advanced javascript and xml?

  96. Stickman on December 7, 2005

    You’re absolutely right. Please see the numerous, similar comments above.

  97. aparch on December 16, 2005

    Oh
    thanks for your help.
    I will come here sometimes for it.

  98. Shrimp on December 18, 2005

    Wow, I see the trackbacks have caused a rather large headache for the author :). I too found this page looking for AJAX information (via Google).

    Don’t really have anything to comment on this script about, but Stickman, I feel your pain ;). People would do well to read the comments and trackpacks before ripping into the author.

  99. Oliver on December 21, 2005

    Hi Folks

    First of all;
    Thank you for publishing this great and neat script!

    I got it work with a GET request ‘only’ but would rather prefer to send the FORM by a POST.
    Does anybody else face this issue or could me explain a work arround?

    Oliver

  100. Oliver on December 22, 2005

    Hello All

    I figured out, that I doesn’t work with FireFox but InternetExplorer.
    If anybody found a workarround for FireFox, I’d very appreciate to learn about.

    Btw. You may wish to see my modifications here: http://www.planetdoom.ch/test/upload_test.php

    Regards
    Oliver

  101. lanner on December 23, 2005

    hello,

    can you explain to me what you put here :

    action=”your_script_here.script”

    i’m not understand about this, thanks a lot

  102. zaila on December 28, 2005

    i have try your code. When i save using “.html”, its work. But, when i save using “.htm”, it doesn’t work. can i know why and how to solve it.

  103. Sourabh on December 28, 2005

    sure it is a real nice way to upload multiple files. but as we have an option of zipping the stuff. this would defeat the idea of having the limit to upload. but sure, it can extend to any limit of uploading..

    keep going….. !!

  104. Mohammad on January 8, 2006

    can anyone tell me in detail that if i chose four image files then ho i and where i go get the valuse to put in my mysql server i am bit confussed please please Help if you can write me a two line of script of insert that would be great i can feed off of that but its a great script very nice hats off to you man but with little more help for novice like me can solve the problem for lots of us out thee how they are trying to learn a thing or two.

  105. James on January 17, 2006

    Well, the script works fine with Firefox 1.0.7 on Mac. So I’d venture to guess that there is something wrong with the usage for the complaint that it doesn’t work on FF 1.0.7

  106. Eric Kaiser on January 24, 2006

    Great script! I’m about as stupid as it comes to stuff like this. I was in search of an inclusive script that not only allowed multiple selection of files to upload, but I wanted it to upload as well. Some of the upload examples on this forum don’t make sense, or are incomplete. I hope to post a change to that. By surfing other sites I came up with a vare bones PHP upload script you can put on your page. There is no resizing of the files or file checking, but I’m sure I will get that going real soon. If anybody wants that feel free to email me.

    Here’s the PHP code that uploads the files:

    foreach ($_FILES["file"]["error"] as $key => $error) {
    echo “key: “.$key.”";
    if ($error == UPLOAD_ERR_OK) {
    $tmp_name = $_FILES["file"]["tmp_name"][$key];
    $name = $_FILES["file"]["name"][$key];
    move_uploaded_file($tmp_name, “tmp/”.$name) or die(’upload error’);
    }
    }

    I made one change to the multifile.js script. Look for the line that reads:

    element.name = ‘file_’ + this.id++;

    This is currently around line 65, and change it to:

    element.name = ‘file[' + this.id++ + ']‘;

    I’m submitting my form onto itself. I have not tested this script if your form action goes to another page.

    Thanks again for this script.

  107. Rich S Wyatt on January 24, 2006

    Hello Stickman! Great work.

    I’m using this in an intranet and have a couple of questions.

    #1 - I would like to modify the output to include some additional text after a file is selected. Right now it simply states the path to the file on the local machine. I’ve played with some pieces of the code to no avail. Can you point me to the line that would allow me to add some things to the path on display?

    For example: Image 1: U:\MyPath\MyImages\bobspic.jpg

    Secondly - when an administrator browses the administration page for a section that may already have some images uploaded:

    Is it possible to recreate what you are doing dynamically with the images that already exist? That way I can “Delete” images that are no longer needed and then catch that all with PHP on the submit of my form.

    Thanks, in advance, for any insight you may give and again: great work!

  108. Steve Owen on January 26, 2006

    Great script, but there does appear to be a bug (feature?) in Firefox. I’ve only tested it in Firefox and IE, and it’s fine in IE, but in Firefox, if you have the script in a table, but the form is outside of the table cell, the new File elements, as they are created, are not assigned to the form. This can be tested by asking the script for the form name of the new element (”undefined”) or keeping count of how many form elements there are (it doesn’t go up). This is almost certainly Mozilla’s unforgiving nesting of tags, and is fair enough, but you do need to watch out for it.

    As an example, in the test page in the zip, put the form name after a table tag but before the tr tag. Submit the form with more than one file and only the first one is uploaded.

    It’s driven me mad for a few days trying to track this down, so I’d spare anyone else the pain.

    Stickman, great script. Thanks.

  109. Steve Owen on January 26, 2006

    Oh, as a follow-up, if anyone’s interested in mods, I’ve added to the script to also just show the filename rather than full path, and to put the Delete button at the start, just as an “X”. It means it all lines up and, I think, looks a lot nicer. You could of course style up the button to make it look even better.

    Because of the innerHTML being affected by putting the button first, you need to put it in its own element. So here’s part of the new script, the this.addListRow function…

    /**
    * Add a new row to the list of files
    */
    this.addListRow = function( element ){

    // Row div
    var new_row = document.createElement( ‘div’ );

    // Delete button
    var new_row_button = document.createElement( ‘input’ );
    new_row_button.type = ‘button’;
    new_row_button.value = ‘X’;

    // References
    new_row.element = element;

    // Delete function
    new_row_button.onclick= function(){

    // Remove element from form
    this.parentNode.element.parentNode.removeChild( this.parentNode.element );

    // Remove this row from the list
    this.parentNode.parentNode.removeChild( this.parentNode );

    // Decrement counter
    this.parentNode.element.multi_selector.count–;

    // Re-enable input element (if it’s disabled)
    this.parentNode.element.multi_selector.current_element.disabled = false;

    // Appease Safari
    // without it Safari wants to reload the browser window
    // which nixes your already queued uploads
    return false;
    };

    // Set row value
    var c = element.value.lastIndexOf(’\/’); //For Unix, etc.
    if (c != -1)
    html = element.value.substring(c+1);
    else {
    var c = element.value.lastIndexOf(’\\’); //Win
    if (c != -1)
    html = element.value.substring(c+1);
    else
    html = element.value;
    }

    // Add button
    new_row.appendChild( new_row_button );
    var new_row_text = document.createElement( ’span’ );
    new_row.appendChild(new_row_text);
    new_row_text.innerHTML = ‘ ’ + html;

    // Add it to the list
    this.list_target.appendChild( new_row );

    };

    I also liked to change the size and class name of the Browse button, which you can add by expanding the MultiSelector object:

    function MultiSelector( list_target, max, class_name, browse_size ){

    and after this.max = -1, these changes:

    this.max = -1;
    };
    this.class_name = class_name;
    this.browse_size = browse_size;

    /**
    * Add a new file input element
    */
    this.addElement = function( element ){

    // Make sure it’s a file input element
    if( element.tagName == ‘INPUT’ && element.type == ‘file’ ){

    // Element name — what number am I?
    element.name = ‘FILE’ + this.id++;
    element.className = this.class_name;
    element.size = this.browse_size;

    // Add reference to this object
    element.multi_selector = this;

    I hope these additions are useful.

  110. Nate on January 27, 2006

    Man, this script works great in all of the browsers -I-, but not in the one browser my company (and subsequently, some of our customers) use!

    Sadly, we’re stuck in the stone age with IE 5.x Mac, and it doesn’t seem to work at all. When I browse/add a file, the file name just sits in the field and doesn’t go anywhere, nor does it appear in the listing below.

    I know I’ve had trouble with CSS in this version of IE, but it mostly had to do with using quotes in url() options, and the classic box-model problems. Since the filename seems to hang in the field, I’m guessing it’s a JS-related issue, and not CSS.

    This makes me sad, because this is the _perfect_ solution to some of our problems. Our customers upload a lot of files to us on a daily basis, and this is so much cleaner than 10 file/browse lines.

    Thanks in advance for any hints

  111. Arminda on January 28, 2006

    Hello,

    can someone help me with uploading the file(s) using the hidden iframe, so that i can upload at the same as i insert the file?

    Execute: ” However I did use an iframe, and just did target=’iframe’, and it works out fine..”, can you show me? I don’t understand?

    Stickman: “However, as I think has been mentioned above you could use a hidden iframe…”, can you?

    Thanks.

  112. Chris on January 31, 2006

    Hi, Just have a quick question. I’m using IE 5.5. I use css for my input fields. On my text input fields I have a border on all four sides. When the page initially loads the border is around my text window but after the first click on the browse button and selecting a file the css disapears and I just have a empty space where the text button should be. It’s still there, just no borders. Any idea how to keep the css?

    Thanks

  113. Chris on January 31, 2006

    I figure it out.

    In you .js file under -

    element.name = ‘file_’ + this.id++;

    add
    element.className = ‘formInputs’; // or what ever class your text input is

    This will pull any class you’ve assigned to the input fields objects and apply it to the new input field object that gets created by the js file.

    You can also do this for the delete button,

    find the following
    new_row_button.value = ‘Delete’;

    add this after
    new_row_button.className = ’submitbutton’; // or what ever class your submitbutton are

    Thanks for the great script.

  114. Tj on February 4, 2006

    Hey everyone, is anyone having problems with the files uploading in IE? It’s not working for me… It works just fine and awesome in FireFox, but IE wont upload the files…

    Thanks for any help! :-D
    -Tj

  115. Ben on February 9, 2006

    Hi, thank for the useful script. I’ve made some changes for a nicer output (table).

    In example.html, changes line <div id=”files_list”></div> to <table id=”files_list”></table>

    In multifile_compressed.js, changes function addListRow as follow:
    this.addListRow = function( element ){

    // Row div
    var new_row = document.createElement( ‘tr’ );
    var new_col_filename = document.createElement( ‘td’ );
    var new_col_button = document.createElement( ‘td’ );

    new_col_filename.setAttribute( ‘align’, ‘left’);
    new_col_button.setAttribute( ‘align’, ‘right’);

    // Delete button
    var new_row_button = document.createElement( ‘input’ );
    new_row_button.type = ‘button’;
    new_row_button.value = ‘Delete’;

    new_row.appendChild( new_col_filename );
    new_row.appendChild( new_col_button );

    // References
    new_row.element = element;

    // Delete function
    new_row_button.onclick= function(){

    // Remove row from table
    this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);

    // Remove element from form
    this.parentNode.parentNode.element.parentNode.removeChild( this.parentNode.parentNode.element );

    // Decrement counter
    this.parentNode.parentNode.element.multi_selector.count–;

    // Re-enable input element (if it’s disabled)
    this.parentNode.parentNode.element.multi_selector.current_element.disabled = false;

    // Appease Safari
    // without it Safari wants to reload the browser window
    // which nixes your already queued uploads
    return false;
    };

    // Set row value
    //new_row.innerHTML = element.value;
    new_col_filename.innerHTML = element.value;
    new_col_button.appendChild( new_row_button );

    // Add it to the list
    this.list_target.appendChild( new_row );

    };

    Hopeful that will help some one.

  116. Kelly on February 15, 2006

    Help!, Updated my mozilla and now this multifile uploader wont work!!!

  117. Steve Owen on February 15, 2006

    Ben’s table code is excellent, but doesn’t actually work in IE. Or rather, isn’t DOM-compliant. (And it’s ironical that IE is the browser that doesn’t like its lack of compliance.)

    Instead, you want to append the child to a element. It’s a simple change. Where you replaced <div id=”files_list”></div> with <table id=”files_list”></table>, you should actually replace <div id=”files_list”></div> with <table><tbody id=”files_list”></tbody></table>

    Cheers,
    Steve

    PS, That has got to be the most annoying “security code” I’ve ever seen. It always takes about four goes and several refreshes to actually work out what it says.

  118. Steve Owen on February 15, 2006

    Sorry, that last comment should have read:

    “Instead, you want to append the child to a <tbody> element.”

  119. Jesse H on February 17, 2006

    Here is vb.net back end implementation after the page is submitted. Someone was asking for it.

    ‘get the form file collection
    Dim myfiles As System.Web.HttpFileCollection = System.Web.HttpContext.Current.Request.Files
    Dim iFile As Integer

    For iFile = 0 To myfiles.Count - 1
    ‘ get the posted file
    Dim postedFile As System.Web.HttpPostedFile = myfiles(iFile)

    ‘make sure it is not blank
    If Not postedFile.FileName.Equals(”") Then
    ‘Save File to the proper directory
    postedFile.SaveAs(Request.MapPath(”folder/”) + System.IO.Path.GetFileName(postedFile.FileName)
    End If

    Next iFile

  120. Jonny on February 20, 2006

    Perfect. Thank you very much for making the script available.

  121. Mark on February 21, 2006

    I want to load several hundred webpages to my typepad blog… can anyone recommend a good program for this? Please email me, thants

  122. Mark on February 21, 2006

    What’s the best telnet program and can they be used on blogs such as typepad?
    http://information.typepad.com

  123. Jorge on February 21, 2006

    Greatfull

  124. Cade on February 22, 2006

    what is the best php for upload with multiple-file???
    Can i use this file so i want or exist a coopyright(by the way i don’t said that it’s my code)?

  125. Stickman on February 22, 2006

    Rather than post my own code for handling the upload at the server end, I’ve left that up to you. There are plenty of good tutorials out there that deal with this — for example, look at this look at this comment or check Google.

    As for usage, you are free to make use of the code in any way you like, although I would appreciate it if you left the copyright information in the file.

  126. Rich on March 7, 2006

    This script is perfect for what I need. Thanks!

    One little problem - it works great the first time, but if I go back to the page, it’s almost like the script has disappeared. When I select a file via the browse button, it doesn’t update the file list, and doesn’t create a new and empty control. I can only upload one file from then on.

    I’ve tried it both Firefox 1.5 and IE 6 and they both act the same. It looks like the DOM is setup properly the second time around, so I’m a bit stymied.

    Any suggestions? I’m using java and struts.

  127. duh on March 7, 2006

  128. Rich on March 7, 2006

    regarding my “doesn’t work the second time post”:

    Turned out that I wasn’t resetting the form correctly.

  129. Bleeding Edge on March 9, 2006

    Looks like IE 7 beta 2 (7.0.5296.0) has a little trouble with this code. It doubles up the elements once a file has been selected. Has anyone else experienced this problem? Has anyone created a fix for this? I will try to look into it more and see if I can find a fix. I’ll keep you posted.

  130. Andy on March 10, 2006

    Nice script, Stickman. I was hoping you or somone else could help me fine tune it to my needs.

    What I’m trying to do is give the user another input box in which to enter a title for the file and then have that title display (instead of the filename) after the user has clicked an “Add to Queue” button (as opposed to displaying immediately after they’ve finished browsing, as the script does currently).

    This is what I’ve tried so far:

    function addFile(){
    var multi_selector = new MultiSelector( document.getElementById( ‘files_list’, 5 ) );
    multi_selector.addElement( document.getElementById( ‘my_file_element’ ) );
    }

    Title:

    File:

    Add

    Files:

    I tried to trigger the display of the filename by using an onclick call to a function containing the instantiation of the MultiSelector class. I can’t figure out why this won’t work. Any help would be greatly appreciated.

    Thanks a lot!

  131. Andy on March 10, 2006

    Crap. Your wysiwyg took that a little too literally. Here’s an attempt to re-post my code. I had to replace “” signs to get it to display, thus all the \’s. I hope it’s not too hard to read. Thanks again!

    function addFile(){
    var multi_selector = new MultiSelector( document.getElementById( ‘files_list’, 5 ) );
    multi_selector.addElement( document.getElementById( ‘my_file_element’ ) );
    }

    Title: \\input type=”text” name=”title_1″\\
    File: \\input id=”my_file_element” type=”file” name=”file_1″\\
    \\a href=”javascript: void(null);” onclick=”addFile();” class=”buttons add”\\Add\\/a\\

    Files:

    \\div id=”files_list”\\ \\/div\\

  132. Bleeding Edge on March 12, 2006

    IE7 beta 2 fires the onchange event twice when you select files using the browse button. Once when a files has been selected. And then once more when it looses focus.
    Blocking the onchange event once it gets executed fixes the problem.
    Changing the code as seen below puts a bandaid on it so it works in IE7 (it also still works in Firefox 1.5).

    // What to do when a file is selected
    element.onchange = function(){
    if (!element.block)
    {
    element.block = true;

    // New file input
    var new_element = document.createElement( ‘input’ );
    new_element.type = ‘file’;

    // Add new element
    this.parentNode.insertBefore( new_element, this );

    // Apply ‘update’ to element
    this.multi_selector.addElement( new_element );

    // Update list
    this.multi_selector.addListRow( this );

    // Hide this: we can’t use display:none because Safari doesn’t like it
    this.style.position = ‘absolute’;
    this.style.left = ‘-1000px’;
    }
    };

  133. Rob Mitchell on March 16, 2006

    Hi - I’m using your script with IE 6.0.2900.2180.xpsp_sp2_rtm.040803-2158 on Windows XP Pro SP2 and results in a Javascript error when trying to submit the form with Access is denied. Any ideas?

    Thanks!

    Rob
    rob@baseclasstech.com

  134. vic on March 20, 2006

    Hi,

    I got a problem with uploading the files:
    I used Shawn Parkers upload script-> http://www.top-frog.com/files/scripts/upload_sample.phps

    But when I try to upload I get this error:

    Warning: move_uploaded_file(C:/Program Files/xampp/htdocshttp://localhost/restricted/upload/uploads/tyson_4.jpg) [function.move-uploaded-file]: failed to open stream: Invalid argument in C:\Program Files\xampp\htdocs\restricted\upload\upload.php on line 119

    Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move ‘C:\Program Files\xampp\tmp\php11.tmp’ to ‘C:/Program Files/xampp/htdocshttp://localhost/restricted/upload/uploads/tyson_4.jpg’ in C:\Program Files\xampp\htdocs\restricted\upload\upload.php on line 119

    Does anyone has an idea what’s wrong?
    regards,

    Vic

  135. Neil on March 29, 2006

    (tip for beginners)
    In PHP this is a good starting point for handling the files

    echo ‘<pre>’;
    print_r ($_POST);
    print_r ($_FILES);
    echo ‘</pre>’;

    Just shows you what you’ve got after the submit.

  136. Lito on April 6, 2006

    This is a added to check if the file all ready exists in the list:

    element.onchange = function () {
    var files = this.parentNode.getElementsByTagName(’input’);
    var existe = new Array();

    for (var i=0; i 1) {
    return false;
    }
    }
    }

  137. Steven on April 7, 2006

    Great Script. Got some problem with it though. I use firefox, php to generate the javascript.

    page1: the multiselector, works fine, no errors, shows the fullpath of the file.

    -submit the form to page2-

    page2: php receive the variable file_”id” as a filename only, instead of the fullpath of the file.

    Anyone else got this kind of problem? Any help would be great.

    Cheers

  138. Anilal on April 7, 2006

    Wonderful file upload component.
    Could some one help me how we can get the files in the backend ASP so as to upload it.
    What will be the File name(s)? any idea or code ..appreciated

    Anilal

  139. Craig on April 8, 2006

    Would it be possible to add all of the file elements to a single array? My php upload class (Easy PHP Uploads) expects an array like…

    _FILES: Array
    (
    [upload] => Array
    (
    [name] => Array
    (
    [0] => FETall.jpg
    [1] => gan_multiplot.plt
    [2] => will-look-up_0_97.zip
    )

    [type] => Array
    (
    [0] => image/jpeg
    [1] => application/octet-stream
    [2] => application/octet-stream
    )

    [tmp_name] => Array
    (
    [0] => C:\WINNT\php59B.tmp
    [1] => C:\WINNT\php59C.tmp
    [2] => C:\WINNT\php59D.tmp
    )

    [error] => Array
    (
    [0] => 0
    [1] => 0
    [2] => 0
    )

    [size] => Array
    (
    [0] => 46676
    [1] => 6713
    [2] => 33271
    )

    )

    )

    Thanks for any advice. I’m no js expert, but with a drawing can probably figure it out. :)
    Cheers.

  140. Melissa on April 8, 2006

    This was quick and easy! You save my time without having to code and look elsewhere. Thanks.

  141. Craig on April 8, 2006

    My appologies this was answered in comment XXXII.

    hint: element.name=’upload[]‘; // d’uh!

  142. thinsoldier on April 10, 2006

    in safari the limit of 3 files is not obeyed.

    And your security code is really hard.

  143. Andrew Bulmer on April 11, 2006

    Not sure if anyone checks this page, but I found a small bug in this. If you click browse twice to bring up 2 file selectors at once and then select a couple of files, one of them can’t be deleted. It throws an error on the following:

    this.parentNode.element.parentNode.removeChild( this.parentNode.element );

    This is because when you open the second selector it tried to remove it twice. I think you might want to do something like this inside the element.onchange function (in addElement):

    this.onchange = function ()
    {
    this.multi_selector.addElement (this) ;
    this.multi_selector.addListRow (this) ;
    } ;

    I’ll have to do some testing to see if that works on the submit side of things

  144. Andrew Bulmer on April 11, 2006

    Well it seems it wasn’t as simple as I first thought. But I do have a solution… I just made the onchange event update the row. To do this I had to make addListRow return the DOM node of the list and add a textnode instead ofusing innerHTML. I also had to make a refernce to the text node and the delete button in the DOM node. Here’s the code for addElement and addList node:

    /**
    * Add a new file input element
    */
    this.addElement = function( element ){

    // Make sure it's a file input element
    if( element.tagName == 'INPUT' && element.type == 'file' ){

    // Element name -- what number am I?
    element.name = 'file_' + this.id++;

    // Add reference to this object
    element.multi_selector = this;

    // What to do when a file is selected
    element.onchange = function(){

    // New file input
    var new_element = document.createElement( 'input' );
    new_element.type = 'file';

    // Add new element
    this.parentNode.insertBefore( new_element, this );

    // Apply 'update' to element
    this.multi_selector.addElement( new_element );

    // Update list
    var row = this.multi_selector.addListRow( this );

    // Hide this: we can't use display:none because Safari doesn't like it
    this.style.position = 'absolute';
    this.style.left = '-1000px';

    this.onchange = function () {

    // just in case the user opens two file selectors at once
    row.removeChild(row.text) ;
    row.text = document.createTextNode (this.value) ;
    row.insertBefore( row.text, row.button );
    }
    };
    // If we've reached maximum number, disable input element
    if( this.max != -1 && this.count >= this.max ){
    element.disabled = true;
    };

    // File element counter
    this.count++;
    // Most recent element
    this.current_element = element;

    } else {
    // This can only be applied to file input elements!
    alert( 'Error: not a file input element' );
    };

    };

    /**
    * Add a new row to the list of files
    */
    this.addListRow = function( element ){

    // Row div
    var new_row = document.createElement( 'div' );

    // Delete button
    new_row.button = document.createElement( 'input' );
    new_row.button.type = 'button';
    new_row.button.value = 'Delete';

    // References
    new_row.element = element;

    // Delete function
    new_row.button.onclick= function(){

    // Remove element from form
    this.parentNode.element.parentNode.removeChild( this.parentNode.element );

    // Remove this row from the list
    this.parentNode.parentNode.removeChild( this.parentNode );

    // Decrement counter
    this.parentNode.element.multi_selector.count--;

    // Re-enable input element (if it's disabled)
    this.parentNode.element.multi_selector.current_element.disabled = false;

    // Appease Safari
    // without it Safari wants to reload the browser window
    // which nixes your already queued uploads
    return false;
    };

    // Set row value
    new_row.text = document.createTextNode (element.value) ;
    new_row.appendChild(new_row.text) ;

    // Add button
    new_row.appendChild( new_row.button );

    // Add it to the list
    this.list_target.appendChild( new_row );

    return new_row ;
    };

    Hope this helps

  145. stephen on April 13, 2006

    great script. i have it working with classic asp. buzz me if you need src.

  146. Fitz on April 16, 2006

    I am using Coldfusion. Can someone give me an example of the backend for the multiupload. I have the front end with no problem but the back end I am not sure how to address after I submit to another page. All the examples are in php that I currently see. Any help is welcomed.

    Thank you in advance.

    Fitz

  147. Fitz on April 17, 2006

    I found the problem with my server end. It had nothing to do with the code it was actually firefox. The deal with having the form delcared within in a table was causing the problem Once I read the above post I found that the form had to be delcared above the table and all is well. For those few that are having to use coldfusion at their job and need this code here it is..

    Could not upload file [#file.serverfile#]

    “>

    “>

    Sorry for the crude formatting.

    Fitz

  148. Fitz on April 17, 2006

    Ooops forgot about the special characters: See if this works better.

    <cfloop from=”0″ to=”#lvMaxNumberFiles#” index=”iItem”>
    <cfset filename = “form.File_#iItem#”>
    <cfif isdefined(”#variables.filename#”)>
    <!— Handle the Pictures\All Folder first —>
    <cfif evaluate(variables.filename) neq “”>
    <cfset lvUploadOkay = “true”>
    <CFTRY>
    <cffile action=”upload” filefield=”#variables.filename#” destination=”#lvPicturesPath#” nameconflict=”unique”></cffile>
    <CFCATCH TYPE=”Any”><cfset lvUploadOkay = “false”><CFOUTPUT><b>Could not upload file [#file.serverfile#]</b><br></cfoutput></CFCATCH>
    </CFTRY>

    <cfif isdefined(”lvUploadOkay”) and lvUploadOkay is ‘true’>
    <cfset message = message & “#file.serverfile# was uploaded successfully<br>”>
    <cfelse>
    <cfset message = message & “#file.serverfile# was not uploaded<br>”>
    </cfif>
    </cfif>
    </cfif>
    </cfloop>

  149. Luca on April 19, 2006

    What do you think about adding this code to the UPLOAD SCRIPT with PROGRESS BAR in AJAX ?! at this site http://php5.bluga.net/progressDemo/demo.php

    thanks

    Luca.

  150. Jesus on April 21, 2006

    El código es genial, un excelente trabajo…
    Thank you.

  151. Tomaž on April 28, 2006

    Very coll code, thanks.

    Tomaž

  152. hudz on April 28, 2006

    Anyone know how to do it with Java-struts? …

    Just email me and I will appreciate it very much, i will put credit on you.

  153. hudz on May 2, 2006

    I have trouble with downlisting the files. I have tried it for several days using java-struts and mozilla FireFox 1.5.0.2. It doesn’t seem to work. I haven’t alter the code, it’s a standard from the downloaded file. Also, what is exactly the function between these two files, multifile.js and multifile_compressed.js, I have read the comments but does not help me. Please Help.

  154. hudz on May 3, 2006

    hi all,

    I have downloaded the files and implemented it at my code, but it seems doesn’t works. I used struts. and im totally new. This is my code

    Zhtml:file property=”attachment” size=”75″ /> Zbr>
    Zdiv id=”files_list”>Zstrong>Files :Z/strong>Z/div>
    Zscript>
    var multi_selector = new MultiSelector( document.getElementById( ‘files_list’ ), 4 );
    multi_selector.addElement( document.getElementById( ‘attachment’ ) );
    Z/script>

    Please tell me what is lack in my code because it does not list down the files..

    this is my email hudzna@gmail.com

    Thank you..very much

  155. derek on May 4, 2006

    hudz, The compressed file is the same code, just smaller in filesize. Just makes your site load faster since there is a smaller download.

  156. hudz on May 4, 2006

    Thank you Derek,

    I’ve noticed it..Sorry for posting a nonsense post. But, Currently I’ve tried to do it with struts but it seems to not working. I’ve posted my code above. Hope anyone can help me.

    Thank you again..

  157. mankind on May 5, 2006

    alert(”Nice Work …..”);

    [Stickman says: Hmm...embedding Javascript in a comment...testing for XSS vulnerabilities? I think maybe you need to read up a bit more on the topic first.]

  158. hudz on May 9, 2006

    in original :

    input id=”my_file_element” type=”file” name=”file_1″ >

    in my struts

    html:file property=”attachment” size=”75″ />

    where should I put name=”file_1″??

  159. Ron W. Waatsveen on May 14, 2006

    Is it possible to hide the tag?
    I have an application with a Java applet that download a file to a spesific catalog on my lokal disk.
    When im finished with my document I push a button that starts an applet who upload the file.
    I dont like this method because its little bit slow and maybe a overkill.
    I also want to say that the applet I use uploads several files at time. I can select a hole folder with files and upload them.

  160. Dave on May 15, 2006

    Hi,

    has anyone used this yet for creating a mail feedback form that in the back-end (php based) mails the attached files? I would be looking for this. Until now I got stuck with pre-defining the number of possible attachments so for the front end this script would be great. Now I’m not so sure how to process the files in the back-end and mail them. Any?

    Thx

    Dave

  161. David Scotti on May 18, 2006

    Does not work in Netscape - and in this world - if it doesn’t work in netscape, then it doesn’t work at all!
    :(

  162. david on May 21, 2006

    Is anone able to give me a piece of code to completly rest the multiuploader? (delete all rows and hidden file input fields). I tried to do this for several hours but it did not work :-(
    Thank you,
    david

  163. derick on May 24, 2006

    Great script. Doesn’t work in Konqueror, though. The file list doesn’t update.

  164. power cord on May 25, 2006

    :)

  165. Prasanna on May 30, 2006

    Hai,,

    Thank you for the Script it working fine .

    Any AJAX based FTP component For c#.NET Development and ASP.NET Development.

    Thank you..

    R.Prasanna Vign