5

I have an HTML form that contains a file input field with multiple file selection and I also have a drag and drop feature that I am working on as well. My question is how to integrate both of these features seamlessly if it is even possible?

Ideally, I would like the user to select their files either through drag'n'drop or through the file dialog box. Once the user is done selecting their files, click the form submit button to upload.

I guess the main uncertainty that I have is how to bind the files that were dragged and dropped to a file input field for form submission.

j0k
  • 22,600
  • 28
  • 79
  • 90
mac2017
  • 445
  • 1
  • 6
  • 16

4 Answers4

1

I wrote some jQuery code that does just that, tell me if it works for you.

<!DOCTYPE html>
<html>
  <head>
    <title>Multiple DnD Uploader</title>
    <link rel="stylesheet" href="style.css" />
    <script type = "text/javascript" src = "../music/jquery.js"></script>
    <script type="text/javascript">
      $(document).ready(function(){
        $('#drop').change(function(event){
          files = event.target.files;
          $('#drop').css('display', 'none');
          for(var i = 0, len = files.length; i < len; i++) {
            if((files[i].fileName+"").substring((files[i].fileName+"").length-4,(files[i].fileName+"").length)=='.mp3'){
            $.ajax({
              type: "POST",
              url: "uploader.php?id="+i,
              contentType: "multipart/form-data",
              headers: {
                "X-File-Name" : files[i].fileName,
                "X-File-Size" : files[i].fileSize,
                "X-File-Type" : files[i].type
              },
              beforeSend:  function() {
                $('#info').append('<li class="indicator"><span class="label">File Name :</span> '+files[i].fileName+' | <span class="label">Size :</span> ' + files[i].fileSize + ' | <img id="'+i+'" src="loading.gif" /></li>');
              },
              processData: false,
              data: files[i],
              success: function(data){
                $('#'+data).attr('src', 'check.png');
              },error: function(data){
                $('#info').append('Error: ' + data + '<br />');
              }
            });
            }else{
              $('#info').append('Error: Incorrect file type. Looking for .mp3');
            }
          }
        });
      });
    </script>
  </head>
  <body>
    <div id="drop">
      <h1>Drop files here</h1>
      <p>To add them as attachments</p>
      <input type="file" multiple="true" id="filesUpload" />
    </div>
    <div id="info">
    </div>
  </body>
</html>

And the PHP file looks like this:

<?php
  $headers = array();
  foreach ($_SERVER as $k => $v){   
    if(substr($k, 0, 5) == "HTTP_"){
      $k = str_replace('_', ' ', substr($k, 5));
      $k = str_replace(' ', '-', ucwords(strtolower($k)));
      $headers[$k] = $v;
    }
  } 
  $file = new stdClass;
  $file->name = basename($headers['X-File-Name']);
  $file->size = $headers['X-File-Size'];
  $file->content = file_get_contents("php://input");
  if(file_put_contents('files/'.$file->name, $file->content))
    echo $_GET['id'];
?>
Vap0r
  • 2,588
  • 3
  • 22
  • 35
  • If I drag a file onto a drop zone, I would like to take that data and append it to the file input field that a user would normally click to get the file dialog box. It's unclear how to go about this or if there is any security issues. Also, if I understand correctly, file input multiple acts as an array so that form submission would send an array of file related data. – mac2017 Jun 03 '11 at 21:33
  • Well, what you can do is just change the success call of the jquery to be something like this: `$('#files').append(files[data].fileName);` Unless I'm misunderstanding you. – Vap0r Jun 04 '11 at 16:38
1

I'm not entirely sure how you're doing it, so I'll tell you the way I do it and then try to answer your question.

  1. Set up event listeners for dropping and <input>'s change event.
    • for dropping: filesUpload.addEventListener("change", function () {traverseFiles(this.files);}, false);
    • for <input>: dropArea.addEventListener("drop", function (evt) {traverseFiles(evt.dataTransfer.files);}, false);
  2. traverseFiles that you see above is a function that gets a FileList (an array of Files), which are a part of the File API. This function then calls a function uploadFile for each File.
  3. uploadFile sends the File asynchronously via ajax (XMLHttpRequest.send(file)).

Now to answer your question how to bind the dropped files to an input field: you don't, you just do it the other way. You create an API or a wrapper for uploading files and then if the user drops files, you call this wrapper function. If the user clicks on the <input> field, you again call this wrapper (like I did with traverseFiles).

Makes sense? If it doesn't, tell me which part and I'll edit this answer / expand on it.

duality_
  • 17,738
  • 23
  • 77
  • 95
0
<input type=file multiple>
<div id='dropzone'>Drop Files Here</div>

onchange and ondrop events shuld bind a function with the variable to get file list.

var files=e.target.files||e.dataTransfer.files

Read This

kongaraju
  • 9,344
  • 11
  • 55
  • 78
-1

You could use "HTML5-File-Uploader" which purports to do what you need as well as gracefully degrade for older browsers:

https://github.com/gre/HTML5-File-Uploader/wiki

I haven't tried it myself.

Alternatively, you could take a look at this page, which supplies all the code you need to do it yourself:

http://robertnyman.com/2010/12/16/utilizing-the-html5-file-api-to-choose-upload-preview-and-see-progress-for-multiple-files/

james.garriss
  • 12,959
  • 7
  • 83
  • 96