简体   繁体   中英

Combining a 'Drop-Zone' with a 'regular file-input'

This is something I fear has been answered before, but I couldn't find anything.

I am working on a modest web application. Part of it is a file-uploader which uploads xml-files to a Java servlet, which are parsed and imported into a database.

Until recently, the html and javascript enabling this looked something like the following (Note that the ironic and/or unhelpful comments are put in place of large chunks of code irrelevant to the question):

html

<form id="import_form">
  <!-- Some irrelevant divs here --> 
  <span class="btn btn-default btn-file">
        Browse <input name="filesToUpload[]" id="filesToUpload" type="file" multiple="" accept="" onchange="updateFileList();"/>
  </span>
  <!-- Some irrelevant divs here --> 
</form>

Javascript

function submitImport() {
    var formData = new FormData($('#import_form')[0]);

    $.ajax({
        url : "uploadEndpoint",
        type : "POST",
        data : formData,
        /* Some more elements */
        success : function(response) {
            // Handle success, it ain't easy
        },
        error : function(request, error, status){
            // Handle failure, weep
        }
    });

The submitImport method is called when the user clicks himself/herself through a set of buttons.

This is all fine and dandy, and works just fine. However, in an effort to make the web application cool and stuff , today, I tried to add a 'drop-zone':

html

<div id="drop-zone">
    <p class="info">Or drop files here</p>
</div>

Javascript

// Handler for the drop-zone
$('#drop-zone').on('dragover', function(event){
    event.preventDefault();
    event.stopPropagation();

    if(!event.dataTransfer){
        event.dataTransfer = event.originalEvent.dataTransfer;
    }

    event.dataTransfer.dropEffect = "copy";
    $(this).css("background-color", "#f5f5f5");

}).on('dragleave', function(event){
    event.preventDefault();
    event.stopPropagation();
    $(this).css("background-color", "#fff");
}).on('drop', function(event){
    event.preventDefault();
    event.stopPropagation();

    if(!event.dataTransfer){
        event.dataTransfer = event.originalEvent.dataTransfer;
    }    

    var files = event.dataTransfer.files;

    // Okey so what now?
});

Still with me? Okey, so my question is the following:

How do I in one chunk send, via $.ajax , the files added both from the "Browse"-input, and the drop-zone?

As indicated by the Okey so what now? comment, I don't really know what to do with the files added in the drop-zone. I can easily fetch the "Browse"-input-form files with

$("#filesToUpload").prop("files");

However, I've come to understand that FileLists are immutable , so that doesn't really help me much, as I cannot append the first to the second.

The one chunk part is vital for application-specific reasons. Consequently, solutions like sequentially sending all FileLists are not ideal.

Note that I am quite the novice in anything web related, so apologies if the answer is staring me in the face.

 var files = event.dataTransfer.files;

// Okey so what now?

Ok, now would be the following:

Yes, the FileList objects are immutable. But you don't need to modify them. Just add the dropped files from FileList to an array named, say, 'files', one by one.

Then, just before calling jQuery.ajax, you can add all files from the files array to the FormData object, as regular fields.

At example:

Step 1 - to remember dropped files

var files = event.dataTransfer.files;

var files = [];
// (be sure to declare 'files' in a scope available in both of ondrop and form-submit methods)

At onDrop:

for(var i = 0;i < event.dataTransfer.files.length;i++) {
    files.push(event.dataTransfer.files.item(i));
    // here you can add some DOM manipulations to show users what files have been dropped here
}

Step 2 - adding files to FormData object

for(var i = 0;i < fileList.length;i++) {
    formData.append('droppedFile[]', fileList[i]);
}

Voilà

The problem is that you can't check for duplicates in subsequent file drops, because the full local path of the file is not accessible for security reasons (it is available on some browsers, but we have not to rely on this unreliable feature).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM