如何区分文件或文件夹在被删除之前是否被拖动?

时间:2014-07-29 13:24:15

标签: javascript html5 drag-and-drop directory

我正在尝试检测是否在 dragover dragenter 事件中拖动了文件夹或文件。

例如:

ondrop事件中,有一个名为MouseEvent的参数,其中包含一个名为dataTransfer的字段,其中列出了文件(.files)或项目({{ 1}}),取决于浏览器,我可以在ChromeFirefox中阅读。但是,对于.itemsdragover个事件,这些字段(dragenter.files)为空。问题是拖动时我需要这些信息,而不是丢弃

注意:对于文件和文件夹.items均为event.dataTransfer.types[i] === "Files"

背景研究

我发现the following answer部分适合我的问题:

  

WebKit,以及Chrome,对于何时可以致电true非常严格。您不允许在getDatadragstart内执行此操作。我认为这是规范的错误。

但是答案是从2012年开始,我无法找到有关该主题的实际更新信息,因此我正在寻找有关此问题的最新信息。

4 个答案:

答案 0 :(得分:88)

TL; DR你不能:(

如果您想知道为什么这个问题仍然没有得到接受的答案,您可以阅读OP创建的this meta question 和{{3 }}

HTML5中的文件drag / drop

我在这个主题的许多文档中做了一些研究,并在各种浏览器上自己测试了,所以我决定总结一下我所知道的关于文件拖放的所有内容。

拖动

拖动文件时,您可以使用一些侦听器,例如:

  • dragenter
  • dragover
  • dragend
  • dragleave

鉴于这些是drag个事件,files的{​​{1}}属性将为event.dataTransfer或为空(length == 0)。

无法读取拖动事件中的文件详细信息,而您无法检查它们是否为文件夹。这不是一个错误,它是一种安全措施。

想象一下,您可以在拖动事件中读取文件:即使用户不想将文件上传到您的网站,您也可以阅读所有内容。认真对待它是没有意义的。想象一下,您正在将文件从桌面拖到另一个文件夹,并且您不小心将其拖动到网页中:现在网页会读取您的文件并将您的个人信息存储在其服务器上...... 这将是一个巨大的安全漏洞

但是,您仍然可以通过迭代数组null来检测用户是否正在拖动文件(以及文件我也指文件夹,因为文件夹是文件)。您可以创建一个函数来检查拖动事件是否包含文件,然后在事件处理程序中调用它。

示例:

event.dataTransfer.types

当您将文件放入drop 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 } } (或您使用dropzone的任何元素)时,您将使用事件<div>的侦听器来读取某些文件属性,例如name,大小,类型和最后修改日期。

要检测文件是否是文件夹,您将:

  1. 检查文件是否有drop,因为文件夹没有类型。
  2. 检查文件大小是否为4096的倍数:type == "",因为文件夹的大小倍数为4096字节(即4KiB)。
  3. 示例:

    size%4096 == 0

    已知问题:由于该文件夹实际上是文件,因此这是将它们与其他类型文件区分开来的唯一方法。虽然此方法无法确定文件是否为文件夹:它可能是没有扩展名且大小为0或N x 4096B的文件。


    工作实例

    以下是一些工作示例,以了解我上面所说的内容并自行测试。在运行它们之前,请确保您的浏览器my answer。玩得开心:

答案 1 :(得分:0)

这是关于Dropping -on drop事件的工作 - (请注意,这不适用于dragover事件):

if matchingEmployee:
print 'Employee(s) found'

for o in matchingEmployee:
    o.food = b

在FF V49,Chrome V55,Edge V25上测试

答案 2 :(得分:0)

您可以使用 FileReader webkitGetAsEntry()

从文件夹中分离文件

ie11不支持webkitGetAsEntry(),因此请记住这一点!

代码如下:

 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);
    }

}

答案 3 :(得分:0)

我能够在页面上获取整个被拖拉的东西的整个Mimetype。 Mimetype对于文件夹似乎是空白的,因此也许您可以通过这种方式区分它。

部分代码(摘自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);

输出如下:

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

当我在页面上拖动3个文件时。

不确定它是否只能在localhost上运行,我还没有在任何地方上传此文件,但是它完全可以正常工作。

MDN docs on DataTransferItem