Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery - Drag n Drop Files - How to get file info?

Interested in building my own drag'n'drop file uploader using JQuery/AJAX/PHP.

Basically I want a file-uploader that users of my site can just drag the file from their computer into a div I created, and it will then upload the file for them to the selected destination.

I would like to build this from scratch, and not use any plugins so that I can better manipulate the restrictions (file types, size, destination folders, etc.)

Have scoured google with no luck, only plugins. Can anyway steer me in the right direction?

UPDATE Ok, so I figured out how to do what I want. Just set the file input field opacity to 1 so it is hidden, and you can still drag a file into that general area and if you hit the text field it will catch it. HOWEVER, I would like to know how to increase the height/width on the file input field (tried basic css on the file, but it only increases the 'browse' button size and not the actual field where you can drop the file into. Any ideas how to do this? I basically want a big square div that says 'Drop file here'. So I need to resize the input field.

like image 483
JimmyJammed Avatar asked Dec 02 '11 22:12

JimmyJammed


2 Answers

Just to chime in here, as I've been doing this as well the last couple of days. From what I understand if you're binding the drop event through jQuery you need to access that event.dataTransfer object by going through the event.originalEvent object in the event provided by jQuery.

Example:

In this I bind to both the dragover as well as drop events, as this was necessary to prevent it from performing the default action (found that solution here: Prevent the default action. Working only in chrome )

$('#dropzone').bind('dragover drop', function(event) {
    event.stopPropagation(); 
    event.preventDefault();
    if (event.type == 'drop') {
        console.log(event.originalEvent.dataTransfer.files);
    }
});

Also there seems to be a bug where if you console.log() the event.dataTransfer (or event.originalEvent.dataTransfer) it's files array is empty, it's pointed out here: event.dataTransfer.files is empty when ondrop is fired?

To better answer the OPs question (I just noticed the rest of it, and I know it's old but some one might find this helpful):

My implementation is in jQuery, so I hope that's alright:

var files = [];

// Attaches to the dropzone to pickup the files dropped on it. In mine this is a div.
$("#dropzone").bind('dragover drop', function(event) {
    // Stop default actions - if you don't it will open the files in the browser
    event.stopPropagation();
    event.preventDefault();

    if (e.type == 'drop') {
        files.push(event.originalEvent.dataTransfer.files);
    }
});

// Attach this to a an input type file so it can grab files selected by the input
$("#file-input").bind('change', function(event) {
    files.push(event.target.files);
});

// This is a link or button which when clicked will do the ajax request 
// and upload the files
$("#upload-button").bind('click', function(event) {
    // Stop the default actions
    event.stopPropagation();
    event.preventDefault();

    if (files.length == 0) {
        // Handle what you want to happen if no files were in the "queue" on clicking upload
        return;
    }

    var formData = new FormData();
    $.each(files, function(key, value) {
        formData.append(key, value);
    });

    $.ajax({
        url: 'upload-ajax',
        type: 'POST',
        data: formData,
        cache: false,
        dataType: 'json',
        processData: false, // Don't process the files - I actually got this and the next from an SO post but I don't remember where
        contentType: false, // Set content type to false as jQuery will tell the server its a query string request
        success: function(data, textStatus, jqXHR) { /* Handle success */ },
        error: function(jqXHR, textStatus, errorThrown) { /* Handle error */ }
    });

});

You could also bind to the other events in the accepted answer for doing effects like making the dropzone fade in so you can see it (that's on my todo list for my library). This is the core of the actual ajax file uploading I use, however.

I don't really have a convenient way to test that, but that's in essence how I did it (I essentially took all that code from the library I've been making and adapted it to fit a general code block on here in an easy to understand way). Hopefully this helps some people out. Starting from here it was actually really easy to go ahead and add in a file queue list, with the ability to delete files from the queue, so this should be a pretty good starting point.

like image 50
Thomas F. Avatar answered Oct 05 '22 04:10

Thomas F.


You can use the HTML5 dragenter and dragleave events to create a dropzone.
Then by placing a file input inside the dropzone, and hiding it with CSS, you can upload the file when the change event for the input fires, like this

var dropzone = $("#dropzone"),
    input    = dropzone.find('input');

dropzone.on({
    dragenter : dragin,
    dragleave : dragout
});

input.on('change', drop);

function dragin(e) { //function for drag into element, just turns the bix X white
    $(dropzone).addClass('hover');
}

function dragout(e) { //function for dragging out of element                         
    $(dropzone).removeClass('hover');
}

function drop(e) {
    var file = this.files[0];
    $('#dropzone').removeClass('hover').addClass('dropped').find('img').remove();

    // upload file here
}

FIDDLE

like image 33
adeneo Avatar answered Oct 05 '22 05:10

adeneo