Javascript 如何区分文件或文件夹在拖放之前是否已被拖动?

Javascript 如何区分文件或文件夹在拖放之前是否已被拖动?,javascript,html,drag-and-drop,directory,Javascript,Html,Drag And Drop,Directory,我正在尝试检测文件夹或文件是否在dragover或dragenter事件中被拖动 例如: 在ondrop事件中,有一个名为MouseEvent的参数,它有一个名为dataTransfer的字段,其中列出了文件(.files)或项目(.items),具体取决于浏览器,我可以在和中读取。但是,对于dragover和dragenter事件,这些字段(.files和.items)为空。问题是,我在拖放时需要这些信息 注意:对于文件和文件夹event.dataTransfer.types[i]==“fil

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

例如: 在
ondrop
事件中,有一个名为
MouseEvent
的参数,它有一个名为
dataTransfer
的字段,其中列出了文件(
.files
)或项目(
.items
),具体取决于浏览器,我可以在和中读取。但是,对于
dragover
dragenter
事件,这些字段(
.files
.items
)为空。问题是,我在拖放时需要这些信息

注意:对于文件和文件夹
event.dataTransfer.types[i]==“files”
true

背景研究 我发现部分符合我的问题:

WebKit和Chrome对何时可以调用
getData
有很大的限制。您不允许在
dragstart
dragover
内执行此操作。我认为这是典型的错误


但是这个答案是2012年的,我找不到关于这个主题的实际更新信息,所以我正在寻找关于这个主题的更新信息;医生,你不行。

如果您想知道为什么这个问题仍然没有得到公认的答案,您可以阅读OP创建的,以及

文件
在HTML5中拖动
/
拖放
我针对这个主题在不同的文档中做了一些研究,并在不同的浏览器上进行了测试,所以我决定在这里总结一下我所知道的关于文件拖放的所有知识

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

  • dragenter
  • dragover
  • dragend
  • dragleave
假设这些是
拖动
事件,则
事件.dataTransfer
文件属性将具有
长度==0
或为空(
null

无法在拖动事件中读取文件详细信息,也无法检查它们是否为文件夹。这不是一个bug,而是一个安全特性。 想象一下,您可以在拖动事件中读取文件:即使用户不想将文件上载到您的站点,您也可以读取所有内容。说真的,这毫无意义。想象一下,您正在将一个文件从桌面拖到另一个文件夹,但不小心将其拖到了一个网页上:现在,该网页将读取您的文件并将您的个人信息存储在其服务器上这将是一个巨大的安全漏洞。

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

例如:

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
    }
}
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
        }
    }
}
已知问题:因为文件夹实际上是文件,所以这是将它们与其他类型的文件区分开来的唯一方法。尽管此方法不能绝对确定文件是文件夹:它可能是一个没有扩展名且大小为0或正好为nx4096b的文件


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

  • (由我制作)
  • (由我制作)
  • (来自css技巧)

这是一个关于拖放事件的工作(请注意,这不适用于dragover事件):


在FF V49、Chrome V55、Edge V25上测试,您可以使用FileReaderwebkitGetAsEntry()从文件夹中分离文件

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

}

我能够在我的页面上得到被拖动的东西的整个模拟类型。对于文件夹,Mimetype似乎为空,所以您可以通过这种方式来区分它

部分代码(从React中提取):

输出如下所示:

file|image/x-icon, file|image/jpeg, file|application/vnd.ms-excel
当我在页面上拖动3个文件时

不确定它是否只在本地主机上工作,我还没有上传到任何地方,但它完全可以工作


我在这里找到了适合我问题的答案(),但现在是2012年,我找不到实际的信息(一个澄清或演示问题的最简单的工作示例可能有助于人们提供高质量的答案。我猜你根本无法做到这一点:如果我在浏览器窗口上拖动一个文件或文件夹到一个无关的位置,该怎么办:如果我拖动的内容不是最重要的,我不希望一个随机网站收集到任何有关该内容的信息。)最终目标。@KristinaKurshakova您应该做正确的事情并接受下面的答案。Marco提供了一个高质量的答案。答案已编辑。这是我能做的最好的答案。很抱歉,但看起来您无法在
拖动事件上读取文件。我知道。我对您问题的回答是,您确实无法检查文件是否是拖动事件上的文件夹ent.对不起,+1关于文件夹的检测,你有两种说法的来源吗?我不认为任何规范都能保证文件夹的大小;这是一个启发式值,不是吗?系统以4KB的块表示文件夹,是的,这实际上是一个启发式值,没有官方方法来区分fil在Chrome 39.0.2171.99的本地文件上,你现在可以查看拖动事件上的数据传输,特别是
ondragenter
ondragover
。这正是OP不需要的。不正确、不相关、混乱、特定于浏览器和基于jQuery。在Safari上有没有同样的方法?我想你可以错过了问题中描述他在工作中如何需要这些信息的部分
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