Ajax CSS

Drag and drop multiple file upload with progress bar

In a previous post i demonstrated how to make Ajax file upload HTML5 drag and drop file upload progress bar which is fine if you are uploading single file, but i found that users are more interested in uploading multiple files at a time. So in this script we will have a look at how to create script which will upload multiple files with progress bar for each upload with drag and drop support.

Great thing is we arent using any flash,swf to achieve our goal HTML5 is enough. Like previous script we will be using HTML5’s File API and HTML5 File Reader Object. I am using Filereader.js jquery plugin instead of manually coding file read function which makes it a much cleaner version, thanks to Brian Grinstead.

You can easily convert the previous script to handle multiple file uploads, Just change the code for XMLHttpRequest() to store each XMLHttpRequest() instance as a distinct object, in this script i have used array index to store the object instances.

Drag and drop multiple file upload with progress bar


 

drag and drop multi file upload (1780)

61 Comments

    • Hi, ty for your script
      I want use it for multi browsers and to perform on IE i would like to add an browse button to select files. Do you think it s possible with your script ? TY

      • Re,

        I found the solution with the documentation of FileReader JS :

        FileReaderJS.setupInput(document.getElementById(‘file-input’), opts);

        😉

  • okay ,I have read all about the f_get_contents(),but now how do i pass the file infor like file size,filename,etc to the php script for echoing to screen

    • Read the file size at the client side using FILE API and send it to server script via same ajax call. In the example “file.size” returns the file size.

  • why are you renaming the file name, yet you already uniquely identified them with the random number id in java script function create_box

    • Its because i didnt want anyone to upload exe file, so no matter what type of file user uploads i forcefully rename it to jpg file. I will suggest you too do not rely on client side javascript validation, validate the file at server side also and then only save that file on disk, User can disable/tweak javascript validation and can upload exe files to your server.

  • can the contents of file_get_contents(‘php://input’) be passed to a function inside a class,like getmyfile->nameof file=file_get_contents(‘php://input’);

  • you have a good approach here but with the f_get_contents() and f_put_contents() ,how are you accounting for memory usage in a very busy file upload system, where many people are actively using it say 1billion.

    • While developing it i didnt consider this case as this was just demonstration of html5 file reader api. My motto was just to demostrate how file reader api can be used.

  • how can i incoporate this example to use a class..My major problem is with the absence of the S_files[ ].where can i get these from the xhr object

    • Why do you want to loop ? it automaticaly tracks the multiple files, I am not sure but while (file_get_contents('php://input') != "") or may be while(strlen(file_get_contents('php://input'))) will work

  • i would like to put in the basic security like check file type against a whitelist of allowed types,file size,content type,etc.And would like to do this using a class.that is why i feel the need to loop through and pass these to my upload class.I need to run the checks on the name ,size and type
    Is this possible?something like this
    $uploader = new Uploader();
    $uploader->setgoodExtensions(array(‘tar’,’tgz’, ‘taz’, ‘z’, ‘gz’, ‘rar’,’txt’)); //allowed extensions list//

  • How can i validate the string of files from the f_get_contents().I have tried it with the $nem=$_SERVER[‘HTTP_X_FILE_NAME’];

    $sze=$_SERVER[‘HTTP_X_FILE_SIZE’];
    $str = file_get_contents(‘php://input’);
    $ext=getExtension($nem);

    $valid_ext = validate_extension($ext);
    if($valid_ext=”true” && $valid_sze=”true” ){file_put_contents(“uploads/”.$nem,$str);}else{//do nothing}
    please assist me here
    but it just keeps uploading all files even those with invalid extensions

    • Shad, i really dont have a clue about how it can be done, i need to study it myself because i have hardly worked on php://input, then only i can suggest you how it can done.

  • hi there, I came across this so far:
    function parse_raw_http_request(array &$a_data)
    {
    // read incoming data
    $input = file_get_contents(‘php://input’);

    // grab multipart boundary from content type header
    preg_match(‘/boundary=(.*)$/’, $_SERVER[‘CONTENT_TYPE’], $matches);

    // content type is probably regular form-encoded
    if (!count($matches))
    {
    // we expect regular puts to containt a query string containing data
    parse_str(urldecode($input), $a_data);
    return $a_data;
    }

    $boundary = $matches[1];

    // split content by boundary and get rid of last — element
    $a_blocks = preg_split(“/-+$boundary/”, $input);
    array_pop($a_blocks);

    // loop data blocks
    foreach ($a_blocks as $id => $block)
    {
    if (empty($block))
    continue;

    // you’ll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char

    // parse uploaded files
    if (strpos($block, ‘application/octet-stream’) !== FALSE)
    {
    // match “name”, then everything after “stream” (optional) except for prepending newlines
    preg_match(“/name=\”([^\”]*)\”.*stream[\n|\r]+([^\n\r].*)?$/s”, $block, $matches);
    $a_data[‘files’][$matches[1]] = $matches[2];
    }
    // parse all other fields
    else
    {
    // match “name” and optional value in between newline sequences
    preg_match(‘/name=\”([^\”]*)\”[\n|\r]+([^\n\r].*)?\r$/s’, $block, $matches);
    $a_data[$matches[1]] = $matches[2];
    }
    }
    }
    $a_data = array();
    parse_raw_http_request($a_data);
    var_dump($a_data);
    ?>
    and displays this:
    array(2) { [“file-input”]=> array(3) { [0]=> string(12) “prototype.js” [1]=> string(11) “msgshow.php” [2]=> string(23) “MOTIVATIONAL LETTER.pdf” } [“submit1”]=> string(6) “submit” }
    how can I pick out only the filename strins from this array???

  • got the data is in an array of arrays and I can get it now.But now how can I alter ths $str variable by deleting from it the filenames that have failed validation???

  • how can I delete from $str
    i have tried this so far but it doesn’t work
    if (in_array( strtolower($ext1), $extensions)) {//if in valid extensions array

    echo $a_data[‘file-input’][$i];

    }else {//delete file from $str
    $mess = str_replace($a_data[‘file-input’][$i],”, $filestring);

    • Shad, i see you are really struggling hard to make this script work, and you are really doing great job by extending this script, but understand that i am not helping you much, But the thing is that my office work keeps me busy too much that i cant enough time for me, not sure if you have noticed or not, but from last 5-6 months i havent posted new post, I am loosing my visitors and google ranking as well.
      Talking about the code you posted, i dont see anything wrong in the code so, save the data in a variable like this $raw_str = $a_data['file-input'][$i] and then print it to see is it holding the right contents and also check the source code to check if there is invalid string in raw data ?

  • Man i got all the arrays,but now how can i alter the $str=f_get_contents(‘php://input’) by deleting the bad files from it.Or how to reconstruct the string without the bad files in it for upload,Or where is the tempname of the files being uploaded? where can i get this from the xhr object???

  • How i can set separate Extensions in var imageType = /image.*/; like var imageType = /image.png/; and ico as well but jpg allowed?image.* will allow all image types

  • Hey bro, its a nice script… But i see if you upload a file using this, you cant remove it. I mean what if a user wants to remove a file after he added the file on the drag n drop place?!

    • I added a few features to this script set, it allows for a list of valid mimeTypes, and then passes the mime type through all the functions to upload(), and changes the post line to this.

      xhr[rand].open(“post”, “ajax_fileupload.php?mimeType=”+encodeURIComponent(mimeType), true);

      likewise you could attach a delete button to each div associated with a file upload, which would execute a post, just like this line, with something like “ajax_delete.php?delete=1&filename=”+encodeURIComponent(mimeType), true); Then just create an ajax_delete.php script which has the line unlink(‘uploads/’.$_GET[‘filename’]) ; Of course this is a bit dangerous, someone could try to hack your site and delete stuff. So you should build in some security.

  • Hi Amit,

    I am using your code for multiple file uploads, its work fine on local machine but showing 500 internal server error while uploading attachment on staging site, our site is on godaddy server. Can you please give us suggestion on this .

    Regards,
    Parag Kamble.

    • There could be many reasons, Check if there is any database error coming up in the code when you run it on server, that can also cause 500 error.

  • I am not a web programmer so snips of code like this from people like you are very useful to me. Thanks!
    I am using this on a password protected page where only myself and one other person will have access to the upload dialog so I am not concerned with any unwanted files being uploaded.
    How can I change this so that the uploaded file retains the original file name and extension?
    Also, is there anything else I should change to allow all file types besides removeing this from script.js ?
    if (!file.type.match(imageType)) {
    alert(“File \””+file.name+”\” is not a valid image file”);
    return false;
    Thanks,
    -Gabe

      • Thank you for your response but unfortunately I am such a beginner and such a dummy that I have no idea how to implement the code from your link to preserve the file name.
        Thank you anyway for taking the time to respond to me and thank you for sharing this handy code.
        -Gabe

  • Hi Amit,
    is it possible to expand this uploader, so you can choose a file by klicking some upload button, so you can browse for the file, without using drag and drop?
    Thanx, Jayden

  • I tried this with both the latest chrome and firefox… fails with more that 3 or 4 files. I do see the correct images on the server. Firefox crashed with 30 files.

    I’m guessing it’s a memory issue. My files are in the 4 to 6M range (images).

    Any thoughts?

  • Tried this code unmodified, and all the times (not matter what file image format) “drops error message. Not a single upload succeeded. It heads to 100%, and then “Error: unexpected error when uploading” – in crome, and mozilla.

      • I use a shared hosting server, and i denied everything with the: “Deny All” option. Previously, I had a code on my page working: a PHP upload script, and had no problem at all. Opening my shared hosting server dir, unable to set any permissions to that directory, and as I said, without any permission chages, I could upload files trough PHP code earlier.

        • Try using previously used php script for uploading files, and check if it works now. If it works now then edit my script and set upload destination to the same folder and check if it works. When you say “It heads 100%” that means script is able to copy your file from your pc to server (temp folder) but after that it moves that file from temp folder to destination provided by you in a code. As per your comment script throws error at this stage which clearly states that there is some issue with the directory permissions and not the code.

          • On the images page, where logged in user can upload images, i just uploaded an image, and had no problem (it was a .png image). More of that, when a user uplaods an image, a special directory structure takes place, with a 192 bit random directory, and image gets copied there.
            I tried yesterday another upload script, what uploads one file, and had progress bar, and worked – file was uploaded. I tried another, what had no progress bar, but uploaded multiple files at once, it was working aswell. So, now i just dont know what is the difference. All those used php code for upload.

          • I am using file_put_contents(“uploads/”.$filename,$str); to write contents to file system, try using some other methods. Code is working fine on my server as well as my local pc.

  • Now i could print it out: it drops error 503. My wabpage hardly ever drops this message, but it rops this message every time, when i try to upload with your code. What could be the reason? Need to adjust something on my server’s settings?

    • May be a server configuration, may be php version. Cant say exactly what causing a problem, You need to debug yourself to find whats causing problem.

      • I use a hosted server, and as I know, the provider always keep up with the latest versions of PHP, SQL, ect. Unfortunately, I have a very little chance to adjust any settings on the server. Thanks for the advices, and help.

      • Hi again! I’m back, but this time, with a GOOD news. I could make the thing working. Actually, it was a server side problem. My host just implemented a new function, a “learning” function onto their server, what can handle 403 errors. I went trough its process, and now its working, like a charm.
        One last thing, I would like to ask. I would like to have the uploaded files stored with their ORIGINAL filename. Could you please help me, where to modify your code, please?
        And: grats for your code, again, the problem wasn’t with you code. 🙂

        • Glad to know it worked. Server side code i am using is pretty basic, i would not recommend it to you. I would suggest you to read this article and comments as well. You can use “getimagesize” and “filesize” functions to get image type and size of the file.

          $size = getimagesize(“uploads/”.$filename);
          print_r($size);

          echo filesize(“uploads/”.$filename);

          • I was asking a question pretty soon, because I could make it work. I made a slight modification in the script.js:

            var addOnsOfURL = ‘?fname=’+file.name+’&fsize=’+file.size+’&ftype=’+file.type;

            xhr[rand].open(“post”, “inc/uploadBox/ajax_fileupload.php”+addOnsOfURL, true);

            and the ajax_fileupload.php:
            $str = file_get_contents(‘php://input’);
            $fileName = $_GET[‘fname’];
            $fileType = $_GET[‘ftype’];
            $fileSize = $_GET[‘fsize’];

            So baiscally I save the filename, filesize, and filetype as variables in the script.js, and send trough to ajax_fileupload.php, where i catch them with a simple $_GET method, after that, I save the file with the original filename, and INSERT the file data to the DB (filename, type, and size).

            I modified more, and now it works with all the type of files, and inserts the real extension tot the db, like: jpg (not ‘image/jpg’), txt (not ‘plain’), ect.
            I made this work with the PATHINFO command:

            $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);

            This throws the real extension of the file, like ‘jpg’, or ‘mp4’, ect.

            I have a restriction for the upload now, its 30 MB, but I tested, and I could upload images, videos, text documents aswell.

            Thank you very much for all the code and help. You may expand your code – if you will – with these changes. 🙂

          • Thumb rule of web development “Never ever trust your visitors” They can be real user of hacker, In your case user can tamper your javascript code and can upload .php file to your server and can easily get access to your server. So you should also check extension on server also. Use “getimagesize” function to check if uploaded file is really a image file ? Only checking last 3 characters is BAD method because it allows files like “bad-file.php.jpg”.

    • Client side code is pure javascript, I am not a java guy so cant provide you complete code, You need to figure out how to read raw http data using java.

Leave a Comment

*

Notify me of followup comments via e-mail. You can also subscribe without commenting.

Shares

Let your friends know what are you reading

Share this post with your friends!