You might have seen at many places like Facebook or even in wordpress editor – “Add Media” section, you could upload multiple images without refreshing the page. After image upload, you could immediately see images preview.
How HTML5 multiple images upload works?
HTML5 provides multiple attributes to select multiple file in input file element.
<form action="multi_files.php" target="hidden_iframe" enctype="multipart/form-data" method="post"> <input type="file" multiple name="upload_files[]" id="upload_files"> </form>
So now you can select multiple files when upload dialog popups up.
Basic HTML5 Setup for multiple images upload
First of all, We’ll hide all elements and use a <button> called “Upload”. It’ll opens up images upload dialog box. Then, once user select files code will auto-submit <form> into <iframe> which calls server side uploading script and upload files.
<div id="upload_form" class="hide"> <form action="multi_files.php" target="hidden_iframe" enctype="multipart/form-data" method="post"> <input type="file" multiple name="upload_files[]" id="upload_files"> </form> </div> <div align="center" style="padding:10px"> <button onclick="Uploader.upload();" class="btn btn-primary btn-lg"> Upload Files </button> <div id="wait" class="hide"> <img src="upload-indicator.gif" alt=""> </div> </div> <div> <iframe name="hidden_iframe" id="hidden_iframe" class="hide"> </iframe> </div> <div id="uploaded_images" align="center"> </div>
Now jQuery Code to trigger uploadbox and start uploading using above hidden iframe.
// this code will open upload dialog box function showUploadDialog() { $('#upload_files').trigger('click'); } // this code will submits form after files have been selected $('#upload_files').on('change', function () { $('#upload_files').parent('form').submit(); });
So, once form is submitted backend script PHP, python, jsp, .NET whatever handles it and send response back in JSON format.
Success Responses:- list of files uploaded.
[ "/uploads/DSC00291.JPG", "/uploads/DSC00297.JPG", "/uploads/DSC00301.JPG", "/uploads/DSC00303.JPG" ]
Error Responses:
{ "error": "Sorry, only images are allowed to upload" }
Code to send and handle this JSON response.
within upload iframe, following javascript code will call parent frame’s uploadDone function
window.parent.uploadDone('<?php echo json_encode($images); ?>');
uploadDone function to handle this response and render images.
function uploadDone(data) { data = JSON.parse(data); if (typeof (data['error']) != "undefined") { $('#uploaded_images').html(data['error']); $('#upload_files').val(""); return; } var divs = []; for (i in data) { divs.push("<div><img src='" + data[i] + "' height='100' class='img-thumbnail'></div>"); } $('#uploaded_images').html(divs.join("")); $('#upload_files').val(""); }
Above code will check, if error is sent then error will be displayed otherwise images will be rendered below upload button.
PHP code to handle multiple-upload at server side.
<?php $failed = false; $images = Array(); $upload_dir = "UPLOAD_DIR_PATH"; if ($_SERVER['CONTENT_LENGTH'] < 8380000) { if (isset($_FILES['upload_files']) && $_FILES['upload_files']['error'] != 0) { foreach($_FILES['upload_files']['tmp_name'] as $key=>$value) { $file = $_FILES['upload_files']['name'][$key]; // allow only image upload if(preg_match('#image#',$_FILES['upload_files']['type'][$key])) { if(!move_uploaded_file($value, $upload_dir.$file)) { $failed = true; } else { $images[] = "WEBSERVER_UPLOAD_DIR_PATH".$file; } } else { $images = array("error"=>"Sorry, only images are allowed to upload"); } } } } else { $images = array("error"=>"Sorry, Upload size exceed allowed upload size of 8MB"); } if($failed == true) { $images = array("error"=>"Server Error<br/>Reported to Admin"); } ?> <html> <body> <script type="text/javascript"> window.parent.Uploader.done('<?php echo json_encode($images); ?>'); </script> </body> </html>
Finally making javascript more modular and non-sucking with closures that doesn’t conflict with global scope.
Writing Upload object with file upload functions.
var Uploader = (function () { jQuery('#upload_files').on('change', function () { jQuery("#wait").removeClass('hide'); jQuery('#upload_files').parent('form').submit(); }); var fnUpload = function () { jQuery('#upload_files').trigger('click'); } var fnDone = function (data) { var data = JSON.parse(data); if (typeof (data['error']) != "undefined") { jQuery('#uploaded_images').html(data['error']); jQuery('#upload_files').val(""); jQuery("#wait").addClass('hide'); return; } var divs = []; for (i in data) { divs.push("<div><img src='" + data[i] + "' style='height:100px' class='img-thumbnail'></div>"); } jQuery('#uploaded_images').html(divs.join("")); jQuery('#upload_files').val(""); jQuery("#wait").addClass('hide'); } return { upload: fnUpload, done: fnDone } }());