Énorme JavaScript HTML5 blob (à partir de grands ArrayBuffers) pour créer un fichier géant dans le côté client

J'écris une application de navigateur Web (client-côté) qui télécharge une quantité énorme de morceaux de plusieurs endroits et les joint pour créer un bloc. Ensuite, ce blob est enregistré dans le système de fichiers local en tant que fichier commun. La façon dont je le fais est au moyen d'objets ArrayBuffer et d'un blob.

var blob = new Blob([ArrayBuffer1, ArrayBuffer2, ArrayBuffer3, ...], {type: mimetype})

Cela fonctionne bien pour les fichiers de petite et moyenne taille (jusqu'à 700 Mo environ), mais le navigateur se bloque avec des fichiers plus importants. Je comprends que la mémoire RAM a ses limites. L'affaire est que je dois construire le blob afin de générer un fichier, mais je veux permettre aux utilisateurs de télécharger des fichiers beaucoup plus grands que cette taille (imaginez, par exemple, des fichiers d'environ 8 Go).

¿Comment puis-je construire le blob en évitant les limites de taille? LocalStorage est plus limité que la RAM, donc je ne sais pas quoi utiliser ou comment le faire.

On dirait que vous ne concatinez que des tableaux de données ensemble? Pourquoi ne pas ajouter de l'ensemble des tampons de réseau dans un bloc géant. Vous devriez iterate et ajouter chaque arrayBuffer un à la fois. Vous seek la fin de l'écriture de fichier pour ajouter des tableaux. Et pour lire seulement des parties de votre gigantesque goutte arrière, vous obtenez une slice de la gouttière pour éviter que le navigateur ne s'écrase.

Fonction d'ajout

 function appendToFile(fPath,data,callback){ fs.root.getFile(fPath, { create: false }, function(fileEntry) { fileEntry.createWriter(function(writer) { writer.onwriteend = function(e) { callback(); }; writer.seek(writer.length); var blob = new Blob([data]); writer.write(blob); }, errorHandler); }, errorHandler); } 

Encore une fois pour éviter de lire l'intégralité du revers, lisez seulement les portions / morceaux de votre gout géant lors de la génération du fichier que vous mentionnez.

Fonction de lecture partielle

 function getPartialBlobFromFile(fPath,start,stop,callback){ fs.root.getFile(fPath, { creation:false }, function(fileEntry){ fileEntry.file(function(file){ var reader = new FileReader(); reader.onloadend = function(evt){ if(evt.target.readyState == FileReader.DONE){ callback(evt.target.result); } }; stop = Math.min(stop,file.size); reader.readAsArrayBuffer(file.slice(start,stop)); }, errorHandler) }, errorHandler); } 

Vous devrez peut-être conserver des index, peut-être dans une section d'en-tête de votre BLOB géant – je devrais en savoir plus avant que je puisse donner des commentaires plus précis.


Mise à jour – éviter les limites de quota, Temporaire vs Persistant en réponse à vos commentaires ci-dessous
Il semble que vous rencontriez des problèmes avec un quota de stockage car vous utilisez un stockage temporaire. Voici un extrait emprunté à Google trouvé ici

Le stockage temporaire est partagé entre toutes les applications Web en cours d'exécution dans le navigateur. Le pool partagé peut représenter jusqu'à la moitié de l'espace disque disponible. Le stockage déjà utilisé par les applications est inclus dans le calcul du pool partagé; C'est-à-dire que le calcul est basé sur (espace de stockage disponible + stockage utilisé par les applications) * .5.

Chaque application peut contenir jusqu'à 20% du pool partagé. À titre d'exemple, si l'espace disque total disponible est de 50 Go, le pool partagé est de 25 Go et l'application peut contenir jusqu'à 5 Go. Ceci est calculé à partir de 20% (jusqu'à 5 Go) de moitié (jusqu'à 25 Go) de l'espace disque disponible (50 Go).

Pour éviter cette limite, vous devrez passer à persistant, cela vous permettra de partager l'espace libre disponible sur le disque. Pour ce faire, procédez comme suit pour initialiser le système de fichiers au lieu de la demande de stockage temporaire.

 navigator.webkitPersistentStorage.requestQuota(1024*1024*5, function(gB){ window.requestFileSystem(PERSISTENT, gB, onInitFs, errorHandler); }, function(e){ console.log('Error', e); })