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

Как я могу сделать очень длинную строку с помощью IndexedDB без сбоев браузера?

Я пишу веб-приложение, которое генерирует потенциально большой текстовый файл, который будет загружен пользователем, и вся обработка выполняется в браузере. Пока я могу читать файл объемом более 1 ГБ в небольших кусках, обрабатывать каждый фрагмент, генерировать большой выходной файл пошагово и хранить растущий результат в IndexedDB. Моя более наивная попытка, которая сохранила все результаты в памяти и затем сериализовала их в файл в самом конце, вызывала сбой всех браузеров.

Мой вопрос в два раза:

  • Могу ли я добавить к записи в IndexedDB (либо строку, либо массив), не прочитав сначала все это в памяти? Прямо сейчас:

    task.dbInputWriteQueue.push(output);
    var transaction = db.transaction("files", "readwrite");
    var objectStore = transaction.objectStore("files");
    var request = objectStore.get(file.id);
    request.onsuccess = function()
    {
        request.results += nextPartOfOutput
        objectStore.put(request.results);
    };
    

    вызывает сбои после того, как результат начинает увеличиваться. Я мог бы просто написать кучу небольших записей в базу данных, но потом мне пришлось бы все их прочитать в памяти позже, чтобы скомпоновать их. См. Часть 2 моего вопроса...

  • Могу ли я сделать URL-адрес объекта данных ссылкой на значение в IndexedDB без загрузки этого значения в память? Для небольших строк я могу сделать:

    var url = window.URL.createObjectURL(new Blob([myString]), {type: 'text/plain'});
    

    Но для больших строк это не слишком хорошо. Фактически, он падает до загрузки строки. Похоже, что большие чтения с использованием get() из IndexedDB заставляют Chrome, по крайней мере, сбой (даже при сбое инструментов разработчика).

Было бы быстрее, если бы я использовал Blobs вместо строк? Это дешевая конверсия?

В принципе, мне нужно с помощью JavaScript написать действительно большой файл на диске, не загружая все это в память в любой момент. Я знаю, что вы можете предоставить createObjectURL файл, но это не работает в моем случае, так как я создаю новый файл из того, который предоставляет пользователь.

4b9b3361

Ответ 1

Сохранение Blob будет использовать намного меньше места и ресурсов, так как больше нет необходимости в преобразовании в base64. Вы даже можете хранить объекты "text/plain" как blobs:

var blob = new Blob(['blob object'], {type: 'text/plain'});
var store = db.transaction(['entries'], 'readwrite').objectStore('entries');

// Store the object  
var req = store.put(blob, 'blob');
req.onerror = function(e) {
    console.log(e);
};
req.onsuccess = function(event) {
    console.log('Successfully stored a blob as Blob.');
};

Вы можете увидеть больше информации здесь: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/

Chrome поддерживает это только с лета 2014 года: http://updates.html5rocks.com/2014/07/Blob-support-for-IndexedDB-landed-on-Chrome-Dev, поэтому вы не можете использовать его в более ранних версиях Chrome.

Ответ 2

Я только что открыла ошибку Chrome, которую я представил 2 года назад, и создал еще одну ошибку для команда FF, связанная с сбоем браузера при создании большого блоба. Создание больших файлов не должно быть проблемой для браузеров.