input[type=file] と Filesystem API の統合

たとえば、写真編集アプリを運用していて、ユーザーが何百枚もの写真をドラッグしてアプリにコピーできるようにしたいとします。どうすればよいでしょうか。

デモを開始
デモを開始

最近の投稿で、Eiji Kitamura は、ドラッグ&ドロップ API の微妙かつ強力な新機能、つまりフォルダをドラッグし、HTML5 Filesystem API の FileEntry および DirectoryEntry オブジェクトとして取得できる機能(DataTransferItem .webkitGetAsEntry() の新しいメソッドにアクセスすることで実現)を紹介しました。

.webkitGetAsEntry() 拡張機能の驚くべき点は、ファイルとフォルダ全体のインポートが洗練されていることです。ドロップ イベントから FileEntry または DirectoryEntry を取得したら、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 を使ってみるをご覧ください。