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.

drag and drop file upload woth progress bar

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.

upload = function(file,rand){
	//upload the file
	var xhr = new Array();
	xhr[rand] = new XMLHttpRequest();
	xhr[rand].open("post", "ajax_fileupload.php", true);

	xhr[rand].upload.addEventListener("progress", function (event) {
		console.log(event);
		if (event.lengthComputable) {
			$(".progress[id='"+rand+"'] span").css("width",(event.loaded / event.total) * 100 + "%");
			$(".preview[id='"+rand+"'] .updone").html(((event.loaded / event.total) * 100).toFixed(2)+"%");
		}
		else {
			alert("Failed to compute file upload length");
		}
	}, false);

	xhr[rand].onreadystatechange = function (oEvent) {  
	  if (xhr[rand].readyState === 4) {  
		if (xhr[rand].status === 200) {  
		  $(".progress[id='"+rand+"'] span").css("width","100%");
		  $(".preview[id='"+rand+"']").find(".updone").html("100%");
		  $(".preview[id='"+rand+"'] .overlay").css("display","none");
		} else {  
		  alert("Error : "+ xhr[rand].statusText);  
		}  
	  }  
	};  

	// Set headers
	xhr[rand].setRequestHeader("Content-Type", "multipart/form-data");
	xhr[rand].setRequestHeader("X-File-Name", file.fileName);
	xhr[rand].setRequestHeader("X-File-Size", file.fileSize);
	xhr[rand].setRequestHeader("X-File-Type", file.type);

	// Send the file (doh)
	xhr[rand].send(file);
}

Drag and drop multiple file upload with progress bar

drag and drop file upload with progressbar

drag and drop multi file upload (829)

About Amit

   Myself Amit Patil from Maharashtra (India). I have been working as a Web Application Developer from last 5+ years, and its my passion to learn new things and implement them as a practice. Basically i am a PHP developer but now a days exploring more in CSS and javascript.

Comments

  1. This doesn’t seem to work in IE9. Is this the case?

    • Unfortunately, Best things never work with IE :(

    • bagarre says:

      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

      • bagarre says:

        Re,

        I found the solution with the documentation of FileReader JS :

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

        ;)

  2. how can I detect that the browser does not support this drag and drop ,so that i display the file browse file input.

  3. how can i display the file size together with the file.

  4. thanks.I’ve figured it out:file.extra.prettySize .But how do i delete /remove files from list

  5. hey how can i display the file details inside the php script.how can i pick them from the f_get_contents()

  6. 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.

  7. 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.

  8. 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’);

  9. how can i use move_files () or copy_files ()

  10. how can I access the temporary file in your case? how do i pass it to pphp with the xhr object.is it there?

  11. 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.

  12. 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

  13. how can i loop through these files with f_gets_contents and f_puts_contents()

    • 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

  14. 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//

  15. 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.

  16. ok. Let me also google around

  17. 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???

  18. 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???

  19. 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 ?

  20. 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???

  21. 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

Speak Your Mind

*


*

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

More in Ajax, CSS, html5 (3 of 37 articles)


    This is simple and most useful script inspired by facebook friends live search script. Live search script can definitely ...