Drag and Drop upload of files

DEMO

Conventional HTML4 has always supported file upload via an html form but it has its limitations. It provides an <input type=”file” /> element to achieve this. This has a limitation that you need to select the file using the browser button.  No progress bar is shown confusing the viewer as to what exactly is happening. You can upload only file at a time and typically any file bigger than 15 MB or so have a tendency to get the script timed out.

HTML5 gives us the ability to drag and drop a file into an html element. This is a very handy feature as a typical web application involves upload of images, PDFs and other documents. This file can then be manipulated to show the preview (in case of an image file) or even uploaded to the server. The user convenience is enhanced by the fact that it allows the user to select multiple files at one go and shows a progress bar for each file upload.

Most articles that we stumbled upon, demonstrated the drag and drop feature and the preview of the file. In a real life scenario, the trickier part is to upload the file to the server with a progress bar. Gmail does it successfully but there was very little documentation on the internet on how to go about doing this. The issue also complicates further as a user can drag multiple files at one time.

Click here to view a demo of drag and drop file upload. The files that you upload will show up from the server once the upload is finished. A brief explanation on how we have tackled this.

For the demo, we shall be using Andrew Valums’ Ajax Upload which can be found at http://valums.com/ajax-upload/.

The script uses XHR to upload multiple files with progress bar in Mozilla Firefox 3.6+, Apple Safari 4+, Google Chrome and gracefully degrades in other browsers using a hidden iframe based normal upload.

The action parameter of the script refers to the path of the server file which is used to handle the uploads to the server. In our example, we are using PHP to transfer files to the server.

When using Drag & Drop to upload files in HTML, files are sent as raw data which can then be accessed via the request body, which is why is not a very good idea to upload really large files. We have found 30MB to be an acceptable limit. Anything above this would crash your browser.

The following snippet of code handles XHR uploads:

function save($path) { // $path is the path we are going to save the file to
    $input = fopen("php://input", "r"); // Read raw data from request body
    $temp = tmpfile(); // Create a temporary file and open a corresponding stream
    stream_copy_to_stream($input, $temp); // Copy stream data to the temporary file
    fclose($input); // Close the file pointer
    $target = fopen($path, "w"); // Open a file pointer to the path we need to save the file to
    fseek($temp, 0, SEEK_SET); // Move to the beginning of the file
    stream_copy_to_stream($temp, $target); // Copy stream data to the destination path
    fclose($target);  // Close the file pointer
    return true;
}

If XHR uploads are not supported as is the case with most Microsoft Internet Explorer browsers, the normal file upload is used and we can access the files using the HTTP File Upload variable $_FILES. The following snippet of code handles the same:

function save($path) { // $path is the path we are going to save the file to
    if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){ // Move the uploaded file to the destination path or else return false
        return false;
    }
        return true;
}
Leave a comment

25 Comments.

  1. I am trying to get this uploader working with my ASP.net application … all works but on chrome and firefox the drag/drop or upload button does not work for mp3, wmv or mov files (It works for any image extension file and mp4 files .. weird behavior ) so i was wondering if anyone could please help me to resolve this issue …

    • Hi Harpreet,

      The Drag & Drop could fail for a couple of reasons:
      1) The size of the media files you are trying to upload may be larger than the limit set. Check the ‘sizeLimit’ parameter and also check your server settings for the maximum upload size.
      2) If the media files are over 30MB, the browser probably would crash depending on your machines’s configuration.

      If you could post a demo of the application, perhaps we could help you debug the issue further.

      Do let us know if you manage to fix the issue.

  2. Hi! I’ve come across your article searching for adding thumbnail support to valum’s ajax uploader (wich I’m using for a project) and since you said you know some tutorials about it, could you tell me links?
    Or even better, how to implement this feature? :P

    Thanks a lot!

    • Hi hiulit,

      The best approach would be to create your thumbnails on the server side and use the uploader object onComplete event to display the created thumbnails once the file has been uploaded.

      Just after

      $result = $uploader->handleUpload(‘uploads/’);

      you could do something like

      $result = $uploader->handleUpload(‘uploads/’);

      // At this point you could use $result to do resizing of images or similar operations
      if(strtolower($result['ext']) == ‘jpg’ || strtolower($result['ext']) == ‘jpeg’){
      $thumbnailPath = createThumbnails($result, ‘uploads/thumbs/’, 75); // Function to create thumbnails

      $result['thumbnailPath'] = $thumbnailPath;
      }

      This will create thumbnails and return the thumbnail path. Then in the uploader object onComplete event you could do something like

      onComplete: function(id, fileName, responseJSON){
      alert(responseJSON.thumbnailPath);
      }

      responseJSON contains all the data that is returned from upload.php which allows us to perform almost any kind of operations on the server side and then return it back to the uploader function. You could also, say for example, add a watermark on your images after uploading and then display the images.

      Hope this helps. Do let us know.

      Regards

      Sapnagroup

  3. I need all of this script to upload images to preview. The same as it was on this page that I showed. If you can send me the script for images with download,

    as you put your script on the page http://html5.sapnagroup.com/demos/dragDropUploads/

    Thank you very much from the heart

    my e-mail is damirmitrovic@hotmail.com

    • Hi Damr,

      If you look into the source of our demo page, you’ll see all the JS code that was used to display thumbnails after the images have been uploaded.

      function createUploader(){
      var uploader = new qq.FileUploader({
      element: document.getElementById(‘fileuploader’),
      action: ‘upload.php’,
      //Files with following extensions are only allowed
      allowedExtensions: ['gif','jpg','jpeg','png','txt'],
      sizeLimit: 10485760, // Maximum filesize limit which works without any problems is 30MB. Current limit is set to 10MB = 10 * 1024 * 1024
      params: {‘uploadedBy’: ‘Sapnagroup’},
      onComplete: function(id, fileName, responseJSON){ // Customize the output sent to responseJSON in upload.php
      switch(responseJSON.ext){
      case ‘gif’:
      case ‘jpg’:
      case ‘jpeg’:
      case ‘png’:
      var imageHTML = ” + fileName + ‘ uploaded by ‘ + responseJSON.uploadedBy + ”;
      document.getElementById(‘imageThumbnails’).innerHTML = document.getElementById(‘imageThumbnails’).innerHTML + imageHTML;
      break;
      default:
      // Do nothing
      break;
      }
      if(uploader._filesInProgress < 1){
      document.getElementById('message').innerHTML = "All files have been uploaded. The page will refresh itself in 10 seconds."
      var t = setTimeout('location.href = location.href;', 10000)
      }
      }
      });
      }

      // Normally you would create uploader as soon as the DOM is ready and would not wait for the window to load
      window.onload = createUploader;

      As you can see ‘onComplete’ allows us to specify what should happen once the images have been upload. In our case, we chose to display the uploaded thumbnails.

      Hope this helps.

  4. Please send me to .zip
    my email damirmitrovic@hotmail.com THANKSSSS :* :)

  5. full script send :D Thankssss

  6. i just can get the ajax response work.. in your demo.. ..

    i just check it using using firebug.. and i saw that there,s are some element besides on success array .. how did u make it work..

    • Hi chris,

      The response array is set in the server script page. For the PHP example, please download the latest files from http://valums.com/ajax-upload/

      You will find the server script page in ‘/server/php.php’. In this page, at the end of the handleUpload function you can specify the response array.

      if ($this->file->save($uploadDirectory . $filename . ‘.’ . $ext)){
      return array(‘success’=>true);
      } else {
      return array(‘error’=> ‘Could not save uploaded file.’ .
      ‘The upload was cancelled, or server error encountered’);
      }

      Here, specify whatever you want to pass on as part of the response array and you can use that in the Drag & Drop script.

      Hope this helps.

      Regards

      sapnagroup

  7. Hi i tried to use the multiple : false options for the drag drop crop preview but it wouldnt work… :sad:

  8. hi sapnagroup,
    how can get the full source code.

    • Hi P.C Roy,

      It would be very difficult for us to give you the entire source code. What part of the code do you need help with?

      Regards,
      sapnagroup

  9. Hi,

    I can upload files but have dudes.

    1 – In demo,if upload fles with the same name changes the name. How?

    2 – How you create path like this:

    ,”path”:”uploads\/e6ccbc169ac43ac59adbf79c50969602\/example.png”

    3 – How add list with files when upload is complete. I can’t show list.

    Thanks

    • Hi Eva,

      Let us answer all you questions:

      1) This happens in the handleUpload function of upload.php

      if(!$replaceOldFile){
      /// don’t overwrite previous files that were uploaded
      while (file_exists($uploadDirectory . $filename . ‘.’ . $ext)) {
      $filename .= rand(10, 99);
      }
      }

      2) Again this happens in the handleUpload function of upload.php

      if ($this->file->save($uploadDirectory . $filename . ‘.’ . $ext)){
      return array(‘success’=>true, ‘path’=>$uploadDirectory . $filename . ‘.’ . $ext, ‘ext’=>$ext, ‘uploadedBy’=>$_GET['uploadedBy']);
      }

      3) In our demo, we simply refresh the page and show the list via PHP.

  10. How is php code inside to show file,icon, and link to path. I can’t do it.

    echo “”;
    echo “”;
    echo “Icon“;
    echo “File Name“;
    echo “Download“;
    echo “”; echo “”; echo “”; echo “”; echo “”.$file.”"; $dir = ‘uploads/’;
    $path = $dir.’/’.$file; echo “Download“; echo “”;
    echo “”;
    ?>

    • Hi David,

      The PHP code is used to display all the uploads during that session. This is pretty standard.

      I think you may be asking about the details of the upload once the upload has finished. This is handled in the onComplete function:

      onComplete: function(id, fileName, responseJSON){ // Customize the output sent to responseJSON in upload.php
      switch(responseJSON.ext){
      case ‘gif’:
      case ‘jpg’:
      case ‘jpeg’:
      case ‘png’:
      var imageHTML = ‘


      ‘ + fileName + ‘ uploaded by ‘ + responseJSON.uploadedBy + ‘

      ‘;
      document.getElementById(‘imageThumbnails’).innerHTML = document.getElementById(‘imageThumbnails’).innerHTML + imageHTML;
      break;
      default:
      // Do nothing
      break;
      }

      if(uploader._filesInProgress < 1){
      document.getElementById(‘message’).innerHTML = “All files have been uploaded. The page will refresh itself in 10 seconds.”
      var t = setTimeout(‘location.href = location.href;’, 10000)
      }
      }

      Regards,
      Eric

  11. where ever i see i found briefly explain…..
    any body explain this step by step.
    and can any one tell me how i can get filename which is uploading

Leave a Reply

Your email address will not be published. Required fields are marked *

*


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>