How to distinguish whether a file or folder is dragged before it is deleted?

I am trying to determine if a folder or file is being dragover into a dragover or dragenter .

For example:

The ondrop event has a MouseEvent argument, which has a field called dataTransfer that lists files ( .files ) or elements ( .items ), depending on the browser, and I can read this in both Chrome and Firefox . However, for dragover and dragenter these fields ( .files and .items ) are empty. The problem is that I need this information when dragging and not when dragging .

NOTE. For files and folders, event.dataTransfer.types[i] === "Files" is true .

Basic research

I found the following answer, which is partially suitable for my question:

WebKit, and therefore Chrome, greatly limits the ability to call getData . You are not allowed to do this inside dragstart or dragover . I think this is a canonical error.

But this answer is from 2012, and I can’t find relevant updated information on this topic , so I am looking for updated information on this issue.

+58
javascript directory html5 folder drag-and-drop
Jul 29 '14 at 13:24
source share
4 answers

TL; DR you cannot :(

If you are wondering why this question has not yet received the accepted answer, you can read this meta-question created by OP, and my answer .

HTML5 drag / drop file

I did some research in many documents on this topic and tested them myself in different browsers, so I decided to summarize everything that I know about dragging and dropping files here.

Drag and drop

When dragging a file, you can use some listeners, for example:

  • dragenter
  • dragover
  • dragend
  • dragleave

Given that these are drag events, the files event.dataTransfer property will either have length == 0 or be null .

You cannot read file data in a drag event, and you cannot check if they are folders. This is not a mistake, it is a safety measure.

Imagine that you can read files during a drag event: you can read everything, even if the user does not want to upload files to your site. That would not make 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 saves your personal information on its server ... which would be a huge security flaw.

However, you can still determine whether the user drags files (as well as files, which I also mean folders, because folders are files) or not, iterating over the array event.dataTransfer.types . You can create a function that checks if the drag event contains files, and then calls 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 } } 

Delete

When you drop the file into drop <div> (or any element that you use as dropzone), you will use the listener for the drop event to read some file properties, such as name, size, type and last modified date.

To determine if a file is a folder, you should:

  • Check if the file is type == "" because the folders are not of type.
  • Check if the file size is a multiple of 4096: size%4096 == 0 , because folders always have a size that is a multiple of 4096 bytes (this 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 these folders are actually files, this is the only way to distinguish them from another type of file. Although this method does not give you complete confidence that the file is a folder: it can be a file without an extension and with a size of 0 or exactly N x 4096B.




Working examples

Here are some working examples to see what I said above and test it yourself. Before starting them, make sure your browser supports drag and drop . Good luck:

+91
Aug 02 '14 at
source share

This is the work on the Dropping -on drop event (note that this does not work with the dragover event):

 isDraggedItemIsFile = function(e) { // handle FF if (e.originalEvent.dataTransfer.files.length == 0) { return false; } // handle Chrome if (e.originalEvent.dataTransfer.items) { if (typeof (e.originalEvent.dataTransfer.items[0].webkitGetAsEntry) == "function") { return e.originalEvent.dataTransfer.items[0].webkitGetAsEntry().isFile; } else if (typeof (e.originalEvent.dataTransfer.items[0].getAsEntry) == "function") { return e.originalEvent.dataTransfer.items[0].getAsEntry().isFile; } } return true; }; $forms.on('drop', function(e) { if (isDraggedItemIsFile(e)) { // do something if file } else{ // is directory } }); 

Tested on FF V49, Chrome V55, Edge V25

0
Sep 27 '16 at 14:33
source share

You can separate files from folders using FileReader or using webkitGetAsEntry ()

WebkitGetAsEntry () is not supported by ie11, so keep that in mind!

The code will look like this:

  onDrop(event) { let files = event.dataTransfer ? event.dataTransfer.files : 'null'; for(let i = 0, file; file = files[i]; i++) { var reader = new FileReader(); reader.onload = function (e) { console.log('it is a file!'); }; reader.onerror = function (e) { console.log('it is a folder!'); }; reader.readAsText(file); } } 
0
Nov 21 '18 at 14:49
source share

I was able to get the whole mimetype of this thing being dragged around my page. Mimetype seems empty for folders, so you might be able to distinguish it this way.

Partial code (extracted from React):

 function handleDragOver(ev: DragEvent) { ev.preventDefault(); ev.dataTransfer!.dropEffect = 'copy'; console.log(Array.from(ev.dataTransfer.items).map(i => [i.kind,i.type].join('|')).join(', ')); } document.addEventListener('dragover',handleDragOver); 

The output looks like this:

 file|image/x-icon, file|image/jpeg, file|application/vnd.ms-excel 

When I drag 3 files onto my page.

Not sure if this only works on localhost, I haven't downloaded it yet, but it works completely.

MDN documents at DataTransferItem

0
Mar 28 '19 at 8:36
source share



All Articles