I am trying to detect if a folder or a file is dragged in the dragover
or dragenter
events.
In the ondrop
event, there is an argument called MouseEvent
, which has a field named dataTransfer
, where are listed files (.files
) or items (.items
), depending on the browser, and I can read that in both Chrome and Firefox. However, for the dragover
and dragenter
events those fields (.files
and .items
) are empty. The problem is that I need that information while dragging, not dropping.
NOTE: For both files and folders event.dataTransfer.types[i] === "Files"
is true
.
I found the following answer to partially fit for my question:
WebKit, and hence Chrome, is quite restrictive on when you can call
getData
. You're not allowed to do it insidedragstart
ordragover
. I think this is the canonical bug.
But that answer is from 2012, and I can't find actual updated information on the topic, so I am looking for updated information on this.
TL;DR you can't.
If you're wondering why this question still hasn't got an accepted answer, you can read this meta question created by OP, and my answer.
drag
/drop
in HTML5I made some research in different pieces of documentation for this topic and tested it by myself on various browsers, so I decided to summarize all I know about drag and drop of files here.
When you drag a file you can use some listeners, such as:
dragenter
dragover
dragend
dragleave
Given that these are drag
events, the files
property of event.dataTransfer
will either have length == 0
or be empty (null
).
Imagine you could read files on a drag event: you would be able to read everything even if the user doesn't want to upload files to your site. It would make no sense, seriously. Imagine you are dragging a file from your desktop to another folder and you accidentally drag it through a web page: now the web page reads your file and stores your personal information on its server... that would be a huge security flaw.
However, you will still be able to detect whether the user is dragging files (and by files I mean folders too, because folders are files) or not by iterating over the array event.dataTransfer.types
. You can create a function that checks if the drag event contains files, and then call it in the event handler.
Example:
function containsFiles(event) {
if (event.dataTransfer.types) {
for (var i=0; i<event.dataTransfer.types.length; i++) {
if (event.dataTransfer.types[i] == "Files") {
return true;
}
}
}
return false;
}
function handleDragEnter(e) {
e.preventDefault();
if (containsFiles(e)) {
// The drag event contains files
// Do something
} else {
// The drag event doesn't contain files
// Do something else
}
}
When you drop a file into the drop <div>
(or whatever element you're using as dropzone), you will use a listener for the event drop
to read some file properties such as name, size, type and last modification date.
To detect if a file is a folder, you are going to:
type == ""
, because folders have no type.size%4096 == 0
, because folders always have a size multiple of 4096 bytes (which is 4KiB).Example:
function handleDrop(e) {
e.stopPropagation();
e.preventDefault();
var files = e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) { // iterate in the files dropped
if (!f.type && f.size%4096 == 0) {
// The file is a folder
// Do something
} else {
// The file is not a folder
// Do something else
}
}
}
KNOWN ISSUE: Since that folders are actually files, this is the only way to distinguish them from another kind of file. Although this method doesn't give you absolute certainty that a file is a folder: it might be a file without extension and with a size of 0 or exactly N x 4096B.
Here are some working examples to see what I said above in action and test it by yourself. Before running them, make sure that your browser supports drag and drop features. Have fun: