Intégrer input[type=file] à l'API Filesystem

Imaginons que vous ayez une application de retouche photo et que vous souhaitiez que les utilisateurs puissent faire glisser des centaines de photos et les copier dans votre application. Ok, que faites-vous ?

Lancer la démo
Lancer la démonstration

Dans un article récent, Eiji Kitamura a mis en avant une nouvelle fonctionnalité subtile, mais puissante, des API de glisser-déposer : la possibilité de glisser-déposer des dossiers et de les récupérer en tant qu'objets FileEntry et DirectoryEntry d'API du système de fichiers HTML5 (accès à une nouvelle méthode sur DataTransferItem, .webkitGetAsEntry()).

Ce qui est remarquable avec l'extension .webkitGetAsEntry(), c'est son élégance lorsqu'elle permet d'importer des fichiers et des dossiers entiers. Une fois que vous avez un FileEntry ou un DirectoryEntry à partir d'un événement "déposer", vous devez utiliser l'élément copyTo() de l'API Filesystem pour l'importer dans votre application.

Exemple de copie de plusieurs dossiers supprimés dans le système de fichiers:

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

Très bien ! Là encore, la simplicité réside dans l'intégration du DNS dans les appels de l'API Filesystem.

Pour aller plus loin, nous avons également la possibilité de glisser-déposer un dossier et/ou des fichiers dans un <input type="file"> normal, puis accéder aux entrées en tant qu'entrées de fichier ou de répertoire de système de fichiers. Cela se fait via .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);

J'ai réalisé une démonstration de galerie photo pour illustrer ces différentes techniques d'importation de fichiers/dossiers.

Lancer la démonstration

Pour en savoir plus sur l'API Filesystem HTML5, consultez Explorer les API Filesystem.