Подтвердить что ты не робот

HTML5 File API, загружающий файл с сервера и сохраняющий его в песочнице

Я пытаюсь понять API HTML5. Я разрабатываю веб-приложение, где браузеру необходимо загружать несколько файлов с сервера; пользователь выполнит что-то с загруженными файлами и приложением, чем нужно сохранить состояние на жестком диске пользователя. Я понимаю, что браузер может сохранять эти файлы только в своей песочнице, что отлично, если пользователь может получить эти файлы во второй раз, когда он запустит приложение. Должен ли я использовать BlobBuilder или FileSaver? Я немного потерялся здесь.

4b9b3361

Ответ 1

Я расскажу вам, как загружать файлы с XMLHttpRequest Level 2 и сохранять их с помощью API файловой системы или с помощью интерфейса FileSaver.

Загрузка файлов

Чтобы загрузить файл, вы будете использовать XMLHttpRequest Level 2 (aka XHR2), который поддерживает запросы с кросс-началом, загрузку событий прогресса и загрузку/загрузку двоичных данных. В сообщении "Новые трюки в XMLHttpRequest2" есть много примеров использования XHR2.

Чтобы загрузить файл как blob, все, что вы сделали, это указать responseType на "blob". Вы также можете использовать типы "text", "arraybuffer" или "document". Функция ниже загружает файл в url и отправляет его в обратный вызов success:

function downloadFile(url, success) {
    var xhr = new XMLHttpRequest(); 
    xhr.open('GET', url, true); 
    xhr.responseType = "blob";
    xhr.onreadystatechange = function () { 
        if (xhr.readyState == 4) {
            if (success) success(xhr.response);
        }
    };
    xhr.send(null);
}

Обратный вызов success получит в качестве аргумента экземпляр Blob, который может быть впоследствии изменен и сохранен и/или загружен на сервер.

Сохранение файлов с API-интерфейсом FileSystem

Как я могу использовать... сайт указывает, что не так много браузеров с поддержкой API FileSystem. Для Firefox есть объяснение из-за отсутствия поддержки. Таким образом, вам придется использовать Chrome для этого.

Сначала вам нужно будет запросить пространство для хранения, оно может быть временным или постоянным. Вероятно, вы захотите иметь постоянное хранилище, в этом случае у вас будет запрос квоты пространства для хранения вверх (некоторые факты):

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.storageInfo = window.storageInfo || window.webkitStorageInfo;

// Request access to the file system
var fileSystem = null         // DOMFileSystem instance
  , fsType = PERSISTENT       // PERSISTENT vs. TEMPORARY storage 
  , fsSize = 10 * 1024 * 1024 // size (bytes) of needed space 
  ;

window.storageInfo.requestQuota(fsType, fsSize, function(gb) {
    window.requestFileSystem(fsType, gb, function(fs) {
        fileSystem = fs;
    }, errorHandler);
}, errorHandler);

Теперь, когда у вас есть доступ к файловой системе, вы можете сохранять и читать файлы с нее. Функция ниже может сохранить blob в указанном пути в файловой системе:

function saveFile(data, path) {
    if (!fileSystem) return;

    fileSystem.root.getFile(path, {create: true}, function(fileEntry) {
        fileEntry.createWriter(function(writer) {
            writer.write(data);
        }, errorHandler);
    }, errorHandler);
}

An, чтобы прочитать файл по этому пути:

function readFile(path, success) {
    fileSystem.root.getFile(path, {}, function(fileEntry) {
        fileEntry.file(function(file) {
            var reader = new FileReader();

            reader.onloadend = function(e) {
                if (success) success(this.result);
            };

            reader.readAsText(file);
        }, errorHandler);
    }, errorHandler);
}

В дополнение к методу readAsText, в соответствии с FileReader API вы можете вызвать readAsArrayBuffer и readAsDataURL.

Использование FileSaver

Сообщение "Сохранение сгенерированных файлов на стороне клиента очень хорошо объясняет использование этого API. Некоторым браузерам может понадобиться FileSaver.js, чтобы иметь интерфейс saveAs.

Если вы используете его вместе с функцией downloadFile, вы можете иметь что-то вроде этого:

downloadFile('image.png', function(blob) {
    saveAs(blob, "image.png");
});

Конечно, было бы разумнее, если бы пользователь мог визуализировать изображение, манипулировать им, а затем сохранять его на своем диске.

Обработчик ошибок

Просто для выполнения примера:

function errorHandler(e) {
    var msg = '';

    switch (e.code) {
        case FileError.QUOTA_EXCEEDED_ERR:
            msg = 'QUOTA_EXCEEDED_ERR';
            break;
        case FileError.NOT_FOUND_ERR:
            msg = 'NOT_FOUND_ERR';
            break;
        case FileError.SECURITY_ERR:
            msg = 'SECURITY_ERR';
            break;
        case FileError.INVALID_MODIFICATION_ERR:
            msg = 'INVALID_MODIFICATION_ERR';
            break;
        case FileError.INVALID_STATE_ERR:
            msg = 'INVALID_STATE_ERR';
            break;
        default:
            msg = 'Unknown Error';
            break;
    };

    console.log('Error: ' + msg);
}

Полезные ссылки

Ответ 3

Мой прием - просто добавить IFRAME с атрибутом "src", указывающим на несколько загрузок. Сайт сервера должен отправить файлы с заголовком "disposition: attachment", а затем клиент попытается сохранить файл локально. Единственная проблема заключается в том, что IFRAME будут оставаться в вашем дереве DOM как обломки, пока пользователь не покинет или не перезагрузит страницу. Сделайте IFRAME невидимым (например, width = 0; height = 0;), и вы готовы к работе! Все браузеры.