File and Directory Entries API broken in Chrome?

假如想象 提交于 2019-12-11 03:25:20

问题


I'm trying to use the File and Directory Entries API to create a file uploader tool that will allow me to drop an arbitrary combination of files and directories into a browser window, to be read and uploaded.

(I'm fully aware that similar functionality can be achieved by using an file input element with webkitdirectory enabled, but I'm testing a use case where the user isn't forced to put everything into a single folder)

Using the Drag and Drop API, I've managed to read the DataTransfer items and convert them to FileSystemEntry objects using DataTransferItem.webkitGetAsEntry.

From there, I am able to tell that if the entry is a FileSystemFileEntry or a FileSystemDirectoryEntry. My plan of course if to recursively walk the directory structure, if any, which I should be able to do using the FileSystemDirectoryReader method readEntries, like this:

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

However, I'm running into the following issue: in Chrome, the readEntries method only returns 100 entries. Apparently, this is the expected behavior as the way to obtain subsequent files from the directory is to call readEntries again. However, I'm finding this impossible to do. A subsequent call to the method throws the error:

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.

Does anyone know a way around this? Is this API hopelessly broken for directories of 100+ files in Chrome? Is this API deprecated? (not that it was ever "precated"). In Firefox, readEntries returns the whole directory content at once, which apparently against the spec, but it is usable.

Please advice.


回答1:


Of course, as soon as I had posted this question the answer hit me. What I was trying to do was akin to the following:

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

The problem with this is that readEntries is asynchronous, so I'm trying to call it while it's "busy" reading the first batch (I'm sure lower-level programmers will have a better term for that). A better way of achieving what I was trying to do:

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

This way we ensure the FileSystemDirectoryReader is done with one batch before starting the next one.



来源:https://stackoverflow.com/questions/51850469/file-and-directory-entries-api-broken-in-chrome

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!