HTML5在火狐浏览器中拖放文件夹的检测,是否可能?

12

我有一个拖放区域,想要检测被拖动的项目是文件夹还是文件。在Chrome中,我使用了以下方法:

for (var i = 0; i < nrOfFiles; i++) {
    var entry = e.originalEvent.dataTransfer.items[i].webkitGetAsEntry();
    if (entry.isDirectory) {
        //folder detection
}

在Firefox浏览器中,无法使用上述解决方案(webkit),经过多次尝试后,我想出了以下解决方案(但都失败了):

  1. 我检查拖动的项目是否没有类型和大小,如下所示,在大多数情况下它能正常工作。根据我所读的资料,这不是高效的,并且并不总是成功的,因为有些文件可能没有文件扩展名,因此我尝试使用FileReader API的readAsBinaryString或readAsArrayBuffer读取文件,并在项目不可读时捕获异常,但是从未抛出异常。

var files = e.originalEvent.dataTransfer.files;
for (var i = 0; i < nrOfFiles; i++) {
if (files[i].size === 0 && files[i].type==="") {

    try{
       var reader = new FileReader();
        reader.readAsBinaryString(files[i]);
    }catch(e){
        //folder detection ?
    }

}}
  • 在下面的解决方案中,我试图使用mozGetDataAt,它是相应的webkitGetAsEntry(??? 如果我错了,请纠正我),但我遇到了安全异常。

  • var entry = e.originalEvent.dataTransfer.mozGetDataAt("application/x-moz-file",i);
    if (entry.isDirectory) { //not even reaching this statement. idk if isDirectory is applicable to entry
        //folder detection?
    }
    

    而异常是:

    拒绝 http://localhost:8080 的权限,以创建未命名类对象的包装器

    在 Firefox 中是否有实际的方法可以解决这个问题?如果可能的话,我不想依赖第三方库或服务器端处理。任何建议和评论都将不胜感激。


    现在可以了!请查看我的答案:https://dev59.com/S2Ag5IYBdhLWcg3wlbxh#33431704 - dforce
    3个回答

    12

    在Firefox 42及以上版本中是可能的 (https://developer.mozilla.org/en-US/Firefox/Releases/42, https://nightly.mozilla.org/):

    https://jsfiddle.net/28g51fa8/3/

    使用拖放事件: e.dataTransfer.getFilesAndDirectories();

    或者,使用一个新的输入对话框,让用户选择文件或文件夹上传:

    <input id="dirinput" multiple="" directory="" type="file" />
    <script>
    var dirinput = document.getElementById("dirinput");
    dirinput.addEventListener("change", function (e) {
      if ('getFilesAndDirectories' in this) {
        this.getFilesAndDirectories().then(function(filesAndDirs) {
            for (var i=0, arrSize=filesAndDirs.length; i < arrSize; i++) {
                iterateFilesAndDirs(filesAndDirs[i]);
            }
        });
      }
    }, false);
    </script>
    

    相关Bugzilla:

    https://bugzilla.mozilla.org/show_bug.cgi?id=1164310(实现微软提出的新FileSystem API的精简子集)

    https://bugzilla.mozilla.org/show_bug.cgi?id=1188880(发布目录选择和目录拖放)

    https://bugzilla.mozilla.org/show_bug.cgi?id=1209924(支持Directory::GetFilesAndDirectories的过滤)

    https://bugzilla.mozilla.org/show_bug.cgi?id=876480#c21(已于2016年11月在Firefox 50中发布)

    部分代码来自:https://jwatt.org/blog/2015/09/14/directory-picking-and-drag-and-drophttps://archive.is/ZBEdF

    不幸的是目前尚未在MS Edge实现:https://dev.modern.ie/platform/status/draganddropdirectories/ 更新:Edge似乎现在有支持了。


    对于Firefox,最终有人必须在“about:config”中创建一个新的布尔属性:dom.input.dirpicker=true。 - dforce
    值得注意的是,输入对话框方法在已发布版本中目前不可用。 - martinez314
    2
    它已在FF50中发布(2016年11月):https://bugzilla.mozilla.org/show_bug.cgi?id=876480#c21 - thomasb
    3
    似乎此内容已被移除。event.dataTransfer.getFilesAndDirectories方法不存在。 - ffxsam
    1
    现在它可以工作了,包括在Firefox和Edge中,参见这个答案,包括拖放和弹出式目录选择器。 - nh2

    5

    以下是我解决这个问题的方法:

    var files = [];
    
    for( var i = 0; i < e.dataTransfer.files.length; i++ ){
        var ent = e.dataTransfer.files[i];
        if( ent.type ) {
            // has a mimetype, definitely a file
            files.push( ent );
        } else {
            // no mimetype:  might be an unknown file or a directory, check
            try {
                // attempt to access the first few bytes of the file, will throw an exception if a directory
                new FileReader().readAsBinaryString( ent.slice( 0, 5 ) ); 
                // no exception, a file
                files.push( ent );
            } catch( e ) {
                // could not access contents, is a directory, skip
            }
        }
    }
    

    基本上:

    • 如果拖放的条目具有MIME类型,则它是文件
    • 否则,尝试读取条目内容
      • 只读取前5个字节(避免意外加载大文件到内存中):ent.slice( 0, 5 )
      • 如果读取成功,则它是文件
      • 如果读取失败,则这是一个目录

    祝使用愉快!


    非常聪明。谢谢你! - Jem
    在所有情况下,这并不会引发异常。在*nix系统中,文件夹大小为4096字节,你可以对文件夹进行切片,它将返回该大小的一个块。 - oliverguenther
    请注意,我的建议是在2016年提出的,已经将近三年了。由于浏览器技术不断变化,无法保证它在2019年仍然有效。 - Dave Cherkassky

    1
    您的问题的简单答案是“不”,在Firefox中没有办法使用拖放方式读取文件夹。
    目前似乎没有处理文件夹的HTML5标准。Chrome处理文件夹的能力是他们在浏览器之外自定义的(超出标准)。
    目前,无法使用HTML5 / JavaScript在Firefox(或IE)中进行文件夹拖放。Mozilla's bugzilla上有一个关于此功能的“错误”,它提到W3C目前已停止创建涵盖目录的文件系统API的标准规范(尽管有editor's draft)。该Mozilla bug仍处于NEW状态,似乎未被分配/接受。
    Microsoft在this unofficial edge document上介绍了该功能,如果您还有关于在IE中尝试此操作的问题,这可能会很有趣。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接