將 input[type=file] 與 Filesystem API 整合

假設您有一個相片編輯應用程式,而且想讓使用者能將數百張相片複製到應用程式中。那麼,您應該怎麼做?

啟動示範
啟動示範

Eiji Kitamura近期貼文中,拖曳 API 提供了細微但強大的新功能;可將資料夾拖曳至資料夾「以及」以 HTML5 Filesystem 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,請參閱探索檔案系統 API