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

Kri*_* Ku 60 javascript directory html5 drag-and-drop

我试图检测是否在dragoverdragenter事件中拖动文件夹或文件.

例如:

在这种情况ondrop下,有一个名为的参数MouseEvent,它有一个名为的字段dataTransfer,其中列出了文件(.files)或项目(.items),具体取决于浏览器,我可以在ChromeFirefox中阅读.但是,对于dragoverdragenter事件,这些字段(.files.items)是空的.问题是我在拖动时需要这些信息,而不是丢弃.

注意:对于文件和文件夹event.dataTransfer.types[i] === "Files"都是true.

背景研究

我发现以下答案部分适合我的问题:

WebKit,以及Chrome,对你什么时候打电话有很大的限制getData.你不允许在里面dragstart或者里面做dragover.我认为这是规范的错误.

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

Mar*_*lli 91

TL; DR你不能:(

如果您想知道为什么这个问题仍未得到接受的答案,您可以阅读 OP创建的这个元问题,以及我的答案.

文件drag/ dropHTML5

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

拖延

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

  • dragenter
  • dragover
  • dragend
  • dragleave

鉴于这些是drag事件,files属性event.dataTransfer将具有length == 0或为空(null).

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

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

但是,您仍然可以通过遍历数组来检测用户是否正在拖动文件(以及文件我也指文件夹,因为文件夹是文件)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
    }
}
Run Code Online (Sandbox Code Playgroud)

删除

当您将文件放入drop <div>(或者您正在使用dropzone的任何元素)时,您将使用该事件的侦听器drop来读取某些文件属性,例如名称,大小,类型和上次修改日期.

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

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

例:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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


工作实例

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

  • 我知道.我对你的问题的回答是,你真的**不能**检查文件是否是拖动事件中的文件夹.对不起. (24认同)
  • 在本地文件的Chrome 39.0.2171.99上,你*现在可以在拖动事件上查看`dataTransfer`,特别是`ondragenter`和`ondragover`. (4认同)
  • +1您是否有关于检测文件夹的两个陈述的来源?我不认为文件夹大小是由任何规范保证; 这是一个启发式的价值,不是吗? (3认同)
  • 回答编辑.这是我能做的最好的事情.对不起,但看起来你**不能**读取'drag`事件的文件. (2认同)
  • 系统表示4KiB块中的文件夹,是的,这实际上是一个启发式值,没有官方方法来区分文件和文件夹. (2认同)
  • 我使用的是 macOS 10.15.6,两个不同文件夹的“size”值为“928”和“992”,所以它绝对不可信。 (2认同)