web-dev-qa-db-fra.com

Enregistrer dans un fichier local à partir de Blob

J'ai une question difficile à vous poser, sur laquelle je lutte depuis un certain temps maintenant.

Je cherche une solution, où je peux enregistrer un fichier sur l'ordinateur des utilisateurs, sans le stockage local, car le stockage local a une limite de 5 Mo. Je veux la boîte de dialogue "Enregistrer dans un fichier", mais les données que je souhaite enregistrer ne sont disponibles qu'en javascript et je voudrais empêcher de renvoyer les données au serveur, puis les renvoyer.

Le cas d'utilisation est que le service sur lequel je travaille enregistre des morceaux compressés et chiffrés des données des utilisateurs, donc le serveur n'a aucune connaissance de ce qui se trouve dans ces morceaux et en renvoyant les données au serveur, cela provoquerait 4 fois le trafic et le serveur reçoit les données non chiffrées, ce qui rendrait tout le chiffrement inutile.

J'ai trouvé une fonction javascript pour enregistrer les données sur l'ordinateur des utilisateurs avec le dialogue "Enregistrer dans un fichier", mais le travail à ce sujet a été interrompu et n'est pas entièrement pris en charge. C'est ceci: http://www.w3.org/TR/file-writer-api/

Donc, comme je n'ai pas de window.saveAs, comment enregistrer les données d'un objet Blob sans tout envoyer au serveur?

Ce serait génial si je pouvais obtenir un indice, que rechercher.

Je sais que cela fonctionne, car MEGA le fait, mais je veux ma propre solution :)

21
fsx_steven

Votre meilleure option est d'utiliser une URL blob (qui est une URL spéciale qui pointe vers un objet dans la mémoire du navigateur):

var myBlob = ...;
var blobUrl = URL.createObjectURL(myBlob);

Vous avez maintenant le choix de simplement rediriger vers cette URL (window.location.replace(blobUrl)), ou de créer un lien vers celle-ci. La deuxième solution vous permet de spécifier un nom de fichier par défaut:

var link = document.createElement("a"); // Or maybe get it from the current document
link.href = blobUrl;
link.download = "aDefaultFileName.txt";
link.innerHTML = "Click here to download the file";
document.body.appendChild(link); // Or append it whereever you want
22
Sebastien C.

FileSaver.js implémente saveAs pour certains navigateurs qui ne l'ont pas

https://github.com/eligrey/FileSaver.js

Testé avec FileSaver.js 1.3.8 testé sur Chromium 75 et Firefox 68, dont aucun n'a saveAs.

Le principe de fonctionnement semble être simplement créer un <a élément et cliquez dessus avec JavaScript oh les horreurs du web.

Voici une démo qui enregistre un blob généré avec canvas.toBlob dans votre dossier de téléchargement avec le nom choisi mypng.png:

var canvas = document.getElementById("my-canvas");
var ctx = canvas.getContext("2d");
var pixel_size = 1;

function draw() {
    console.log("draw");
    for (x = 0; x < canvas.width; x += pixel_size) {
        for (y = 0; y < canvas.height; y += pixel_size) {
            var b = 0.5;
            ctx.fillStyle =
                "rgba(" +
                (x / canvas.width) * 255 + "," +
                (y / canvas.height) * 255 + "," +
                b * 255 +
                ",255)"
            ;
            ctx.fillRect(x, y, pixel_size, pixel_size);
        }
    }
    canvas.toBlob(function(blob) {
      saveAs(blob, 'mypng.png');
    });
}
window.requestAnimationFrame(draw);
<canvas id="my-canvas" width="512" height="512" style="border:1px solid black;"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js"></script>

Voici une version animée qui télécharge plusieurs images: Convertir la séquence HTML5 Canvas en un fichier vidéo

Voir également: