Integrazione di input[type=file] con l'API filesystem

Supponiamo che tu abbia un'app di fotoritocco e che tu voglia che gli utenti possano trascinare centinaia di foto e copiarle nella tua app. Ok, cosa fai?

Avvia demo
Avvia demo

In un post recente, Eiji Kitamura ha evidenziato una nuova funzionalità sottile, ma potente, nelle API di trascinamento: la possibilità di trascinare cartelle e recuperarle come oggetti FileEntry e DirectoryEntry dell'API Filesystem HTML5 (ottenuta accedendo a un nuovo metodo su DataTransferItem, .webkitGetAsEntry()).

La cosa davvero interessante dell'estensione .webkitGetAsEntry() è la semplicità con cui consente di importare file e intere cartelle. Una volta ottenuto un FileEntry o un DirectoryEntry da un evento di rilascio, devi utilizzare copyTo() dell'API Filesystem per importarli nella tua app.

Un esempio di copia di più cartelle nel file system:

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

Molto bene. Anche in questo caso, la semplicità deriva dall'integrazione di DnD con le chiamate all'API Filesystem.

Facendo un ulteriore passo avanti, abbiamo anche la possibilità di trascinare una cartella e/o file in un normale <input type="file">, quindi di accedere alle voci come directory del file system o voci di file. Ciò avviene tramite .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);

Ho creato una demo di una galleria fotografica per dimostrare queste diverse tecniche di importazione di file/cartelle.

Avviare la demo

Per scoprire di più sull'API Filesystem HTML5, consulta Esplorazione delle API Filesystem.