将输入 [type=file] 与 Filesystem API 集成

假设您有一个照片编辑应用,并且希望用户能够拖动数百张照片并将其复制到您的应用中。那么,您该怎么做?

启动演示
启动演示

一篇近期的博文中,Eiji Kitamura 重点介绍了拖放 API 中一项细微但强大的新功能:能够拖放文件夹,将其检索为 HTML5 文件系统 API FileEntryDirectoryEntry 对象(通过访问 DataTransferItem 上的新方法 .webkitGetAsEntry() 来实现)。

.webkitGetAsEntry() 扩展程序的一大亮点在于,它可以非常优雅地导入文件和整个文件夹。从拖放事件中获取 FileEntryDirectoryEntry 后,只需使用 Filesystem API 的 copyTo() 将其导入到应用中即可。

将多个拖放的文件夹复制到文件系统的示例:

var fs = null; // Cache filesystem for later.

// Not shown: setup drag and drop event listeners.
function onDrop(e) {
    e.preventDefault();
    e.stopPropagation();

    var items = e.dataTransfer.items;

    for (var i = 0, item; item = items[i]; ++i) {
    var entry = item.webkitGetAsEntry();

    // Folder? Copy the DirectoryEntry over to our local filesystem.
    if (entry.isDirectory) {
        entry.copyTo(fs.root, null, function(copiedEntry) {
        // ...
        }, onError);
    }
    }
}

window.webkitRequestFileSystem(TEMPORARY, 1024 * 1204, function(fileSystem) {
    fs = fileSystem;
}, function(e) {
    console.log('Error', e);
});

太棒了!再次强调一下,这种简单性源自将 DnD 与文件系统 API 调用集成。

更进一步,我们还可以将文件夹和/或文件拖放到常规 <input type="file"> 上,然后以文件系统目录或文件条目的形式访问这些条目。这通过 .webkitEntries 完成:

<input type="file" multiple>
function onChange(e) {
    e.stopPropagation();
    e.preventDefault();

    var entries = e.target.webkitEntries; // Get all dropped items as FS API entries.

    [].forEach.call(entries, function(entry) {

    // Copy the entry into our local filesystem.
    entry.copyTo(fs.root, null, function(copiedEntry) {
        ...
    }, onError);

    });
}

document.querySelector('input[type="file"]').addEventListener('change', onChange);

我制作了一个照片库演示,演示了导入文件/文件夹的这些不同方法。

启动演示

如需详细了解 HTML5 文件系统 API,请参阅探索文件系统 API