web-dev-qa-db-fra.com

Télécharger un flux de données volumineux (> 1 Go) en utilisant javascript

Je me demandais s'il était possible de diffuser des données de javascript au gestionnaire de téléchargements du navigateur.

En utilisant webrtc, je diffuse des données (à partir de fichiers> 1 Go) d'un navigateur à l'autre. Côté récepteur, je stocke en mémoire toutes ces données (comme arraybuffer ... donc les données sont essentiellement encore des morceaux), et j'aimerais que l'utilisateur puisse les télécharger.

Problème: Les objets Blob ont une taille maximale d'environ 600 Mo (selon le navigateur), donc je ne peux pas recréer le fichier à partir des morceaux. Existe-t-il un moyen de diffuser ces morceaux afin que le navigateur les télécharge directement?

12
Brian

Suivant les conseils de @ guest271314, j'ai ajouté StreamSaver.js à mon projet, et j'ai réussi à recevoir des fichiers de plus de 1 Go sur Chrome. Selon la documentation, cela devrait fonctionner pour des fichiers jusqu'à 15 Go, mais mon navigateur s'est planté auparavant (la taille maximale du fichier était d'environ 4 Go pour moi).

Remarque I: pour éviter la limitation de taille maximale de Blob, j'ai également essayé d'ajouter manuellement des données au champ href d'un <a></a> mais il a échoué avec des fichiers d'environ 600 Mo ...

Note II: aussi incroyable que cela puisse paraître, la technique de base utilisant createObjectURL fonctionne parfaitement sur Firefox pour des fichiers jusqu'à 4 Go !!

3
Brian

si vous souhaitez récupérer un gros fichier blob à partir d'une API ou d'une URL, vous pouvez utiliser streamsaver.

npm install streamsaver

alors vous pouvez faire quelque chose comme ça

import { createWriteStream } from 'streamsaver';

export const downloadFile = (url, fileName) => {
  return fetch(url).then(res => {
    const fileStream = createWriteStream(fileName);
    const writer = fileStream.getWriter();
    if (res.body.pipeTo) {
      writer.releaseLock();
      return res.body.pipeTo(fileStream);
    }

    const reader = res.body.getReader();
    const pump = () =>
      reader
        .read()
        .then(({ value, done }) => (done ? writer.close() : writer.write(value).then(pump)));

    return pump();
  });
};

et vous pouvez l'utiliser comme ceci:

const url = "http://urltobigfile";
const fileName = "bigfile.Zip";

downloadFile(url, fileName).then(() => { alert('done'); });
2
David