Domanda Come posso creare una stringa veramente lunga usando IndexedDB senza arrestare il browser?


Sto scrivendo un'app Web che genera un file di testo potenzialmente di grandi dimensioni che l'utente scaricherà e tutta l'elaborazione viene eseguita nel browser. Finora sono in grado di leggere un file superiore a 1 GB in piccoli blocchi, elaborare ogni blocco, generare un file di output di grandi dimensioni in modo incrementale e archiviare l'output in crescita in IndexedDB. Il mio tentativo più ingenuo, che ha mantenuto tutti i risultati in memoria e li ha serializzati in un file alla fine, ha causato il blocco di tutti i browser.

La mia domanda è duplice:

  1. Posso aggiungere una voce in IndexedDB (una stringa o un array) senza leggere prima l'intera cosa in memoria? In questo momento, questo:

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

    sta causando arresti anomali dopo che l'uscita inizia a diventare grande. Potrei semplicemente scrivere un po 'di piccole voci nel database, ma poi dovrei leggerle tutte in memoria comunque per concatenarle. Vedi la parte 2 della mia domanda ...

  2. Posso creare un URL dell'oggetto dati per fare riferimento a un valore in IndexedDB senza caricare quel valore in memoria? Per piccole stringhe posso fare:

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

    Ma per grandi stringhe questo non va troppo bene. Infatti, si blocca prima che la stringa venga caricata. Sembra che si usi grandi letture get() da IndexedDB causa almeno l'arresto anomalo di Chrome (anche gli strumenti degli sviluppatori si bloccano).

Sarebbe più veloce se usassi Blob anziché stringhe? Questa conversione è a buon mercato?

Fondamentalmente ho bisogno di un modo, con JavaScript, per scrivere un file veramente grande su disco senza caricare l'intera cosa in memoria in un punto qualsiasi. So che puoi dare createObjectURL un file, ma questo non funziona nel mio caso poiché sto generando un nuovo file da uno fornito dall'utente.


27
2017-11-22 19:59


origine


risposte:


La memorizzazione di un Blob utilizzerà molto meno spazio e risorse in quanto non è più necessaria la conversione in base64. Puoi anche memorizzare oggetti "text / plain" come blob:

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

Puoi vedere maggiori informazioni qui: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/

Chrome ha supportato questo solo dall'estate 2014: http://updates.html5rocks.com/2014/07/Blob-support-for-IndexedDB-landed-on-Chrome-Dev quindi non puoi usarlo nelle versioni precedenti di Chrome.


6
2017-12-18 21:17



Ho appena riaperto il Bug di Chrome  che ho presentato 2 anni fa e ho creato un altro bug per il Squadra FF, relativo al crash del browser durante la creazione di un blob di grandi dimensioni. La generazione di file di grandi dimensioni non dovrebbe essere un problema per i browser.


0
2018-01-10 17:59