將 input[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 與 Filesystem 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 FileSystem API,請參閱「探索 FileSystem API」。