【问题标题】:File and Directory Entries API broken in Chrome?Chrome 中的文件和目录条目 API 是否损坏?
【发布时间】:2019-01-21 20:16:40
【问题描述】:

我正在尝试使用文件和目录条目 API 创建一个文件上传工具,该工具允许我将文件和目录的任意组合拖放到浏览器窗口中,以供读取和上传。

(我完全意识到可以通过使用启用webkitdirectory 的文件输入元素来实现类似的功能,但我正在测试一个用户不必将所有内容都放入单个文件夹的用例)

使用拖放 API,我设法读取了 DataTransfer 项目并使用 DataTransferItem.webkitGetAsEntry 将它们转换为 FileSystemEntry 对象。

从那里,我可以判断该条目是FileSystemFileEntry 还是FileSystemDirectoryEntry。我的计划当然是递归遍历目录结构(如果有的话),我应该可以使用FileSystemDirectoryReader 方法readEntries 来执行此操作,如下所示:

handleDrop(event) {
    event.preventDefault();
    event.stopPropagation();
    //assuming I dropped only one directory
    const directory = event.dataTransfer.items[0];
    const directoryEntry = directory.webkitGetAsEntry();
    const directoryReader = directoryEntry.createReader();
    directoryReader.readEntries(function(entires){
        // callback: the "entries" param is an Array 
        // containing the directory entries
    });
}

但是,我遇到了以下问题:在 Chrome 中,readEntries 方法仅返回 100 个条目。显然,这是预期的行为,因为从目录中获取后续文件的方法是再次调用readEntries。但是,我发现这是不可能的。对该方法的后续调用会引发错误:

DOMException: An operation that depends on state cached in an interface object was made but the state had changed since it was read from disk.

有人知道解决这个问题的方法吗?对于 Chrome 中 100 多个文件的目录,这个 API 是否被彻底破坏了?此 API 是否已弃用? (并不是说它曾经被“推荐”过)。在 Firefox 中,readEntries 一次返回整个目录内容,这显然违反规范,但它是可用的。

请指教。

【问题讨论】:

    标签: javascript html fileapi


    【解决方案1】:

    当然,一旦我发布了这个问题,答案就立即出现了。我试图做的类似于以下内容:

    handleDrop(event) {
        event.preventDefault();
        event.stopPropagation();
        //assuming I dropped only one directory
        const directory = event.dataTransfer.items[0];
        const directoryEntry = directory.webkitGetAsEntry();
        const directoryReader = directoryEntry.createReader();
        directoryReader.readEntries(function(entries){
            // callback: the "entries" param is an Array 
            // containing the directory entries
        }, );
        directoryReader.readEntries(function(entries){
            //call entries a second time
        });
    }
    

    这个问题是 readEntries 是异步的,所以我试图在它“忙”读取第一批时调用它(我相信低级别的程序员会有一个更好的术语)。实现我想要做的事情的更好方法:

    handleDrop(event) {
        event.preventDefault();
        event.stopPropagation();
        //assuming I dropped only one directory
        const directory = event.dataTransfer.items[0];
        const directoryEntry = directory.webkitGetAsEntry();
        const directoryReader = directoryEntry.createReader();
    
        function read(){
            directoryReader.readEntries(function(entries){
                if(entries.length > 0) {
                    //do something with the entries
                    read(); //read the next batch
                } else {
                    //do whatever needs to be done after
                    //all files are read
                }
            });
        }
        read();
    }
    

    这样我们确保FileSystemDirectoryReader 在开始下一批之前完成了一批。

    【讨论】:

    • 您在那里发现的有趣的使用问题;本来希望文档会注意到这一点,但这是一个“非标准”功能。也可以使用await/async 来执行此操作,类似于stackoverflow.com/a/53058574/885922
    猜你喜欢
    • 2016-09-30
    • 1970-01-01
    • 2017-04-10
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    相关资源
    最近更新 更多