Por qué FileSaver saveAs no funciona con un JSZip?

0

Pregunta

Primera vez que posteo, este es el código completo (la mayoría de los que he encontrado en internet y ajustado algunas cosas para servir a mi propósito), pero más específicamente, mi error es hacia el final donde puedo llegar.

Uncaught TypeError: Error al ejecutar 'createObjectURL' en 'URL': resolución de Sobrecarga fallado.

Cuando yo simplemente uso saveAs(img_url, "img.png"), la opción para guardar el portátil aparece. Pero me da el error que he mencionado anteriormente cuando se intenta utilizar el "contenido". He filesaver y jszip en el script, me parece que no puede encontrar alguna manera de corregir el error, que entonces deja de ejecutar nada más. Lo siento por el código desordenado, realmente le agradezco la ayuda.

Parte principal es hacia la parte inferior, el resto es no sólo en caso de que alguien quiera ver. Theres la url a blob, a continuación, el lienzo generador, yo no sé por qué no guardar.

!function() {
    function dataURLtoBlob(dataURL, type) {
      var binary = atob(dataURL.split(',')[1]),
          length = binary.length,
          binaryArray = new Uint8Array(length);
      for (var i = 0; i < length; i++) {
        binaryArray[i] = binary.charCodeAt(i);
      }
      return new Blob([binaryArray], {type: type});
    }

    var SolidImage = function() {
      var canvas = document.createElement('canvas'),
          ctx = canvas.getContext('2d');
      this.img = new Image();
      this.make = function(color) {
        canvas.width = 500;
        canvas.height = 500;
        
        ctx.fillStyle = color;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "#FFFFFF";
        ctx.textAlign = "center";
        ctx.font = "bold 50px Courier New";
        ctx.fillText(color.substring(3), 250, 250);
        var dataURL = canvas.toDataURL('image/png')
        this.img.src = dataURL;
        if (this.blobURL) URL.revokeObjectURL(this.blobURL);
        this.blob = dataURLtoBlob(dataURL, 'image/png');
        this.blobURL = URL.createObjectURL(this.blob);
      }
    };
    
    var solidImage = new SolidImage(),
        button = document.getElementById('make'),
        result = document.getElementById('result'),
        link = document.createElement('a');
    
    link.setAttribute('target', '_blank');
    result.appendChild(solidImage.img);
    result.insertAdjacentHTML('beforeend', 'Save this image or<br>');
    result.appendChild(link);
    solidImage.img.width = 600;
  
    
    button.addEventListener('click', function(){
        var zip = new JSZip();
        console.log("after zip");
        //var img = zip.folder("rdm_imgs");
        //////////////////////////////////
        for (var i = 0; i < 1; i++) {
            setTimeout(function() {
        var rgb_r = Math.floor(Math.random() * (256+1)),
            rgb_g = Math.floor(Math.random() * (256+1)),
            rgb_b = Math.floor(Math.random() * (256+1)),
            random_color = "rgb(" + rgb_r + ", " + rgb_b + ", " + rgb_g + ")";
      var filename = random_color.replace(/\s/g, "") + '.png';
      solidImage.make(random_color);
      link.innerHTML = 'Download content ' + filename;
      var img_url = solidImage.blob;
      //console.log(img_url.replace(/^data:image\/(png|jpg);base64,/, ""));
      console.log(img_url);
      //link.setAttribute('href', img_url);
      //link.setAttribute('download', filename);
      result.className = 'generated';

      zip.file(filename, img_url);
            },i * 500)}
        console.log("after loop");
        var content = zip.generateAsync({type:"blob"});
        console.log("after zip generate");
        saveAs(content, "imgs.zip");
        console.log("after saveAs");
        //link.innerHTML = 'Download Contents.zip';
        //var img_url = solidImage.blobURL;
        //link.setAttribute('href', content);
        //link.setAttribute('download', "content.zip");
    });
  }();
blob filesaver.js javascript jszip
2021-11-21 21:48:48
1

Mejor respuesta

1

zip.gzip.generateAsync() devuelve una Promesa. Esta Promesa se va a resolver con un Blob, algunas veces más tarde, pero es una Promesa, no una nota.
Así que usted necesita a la espera de la resolución de esta Promesa para acceder a la generada Blob.

Usted puede marcar su función como async y, a continuación, utilizar la await palabra clave:

button.addEventListener('click', async function(){
  // ...
  var content = await zip.generateAsync({type:"blob"});

O envuelva la saveAs parte en una devolución de llamada pasa a la Promesa del .then():

zip.generateAsync({type:"blob"}).then(function(content) {
  console.log("after zip generate");
  saveAs(content, "imgs.zip");
})

Ahora, lo que usted elija, su archivo zip en realidad estar vacío. Se le añade contenido sólo en la devolución de llamada de setTimeout, lo que significa que este contenido será agregado sólo después de que usted hizo crear el archivo zip, que es demasiado tarde.
Por lo tanto, eliminar la setTimeout( la parte que parece inútil y ejecutar su devolución de llamada del contenido directamente.

2021-11-21 23:32:28

Yo había usado el setTimeout para añadir un retardo cuando visualmente viendo el cambio a través de colores al azar en la página HTML. Voy a tratar de que, a pesar de cómo es que la postal sea vacía? Pero supongo que desde que inicializar el zip tan pronto como se hace clic en, a continuación, dentro del bucle voy a agregar los archivos a la carpeta zip?
absolutenoob

Wow, esto ha funcionado, muchas gracias. Si pudiera, podría tal vez explicar por qué, específicamente, que era la cuestión?
absolutenoob

El problema que causa el "Uncaught TypeError: Error al ejecutar 'createObjectURL' en 'URL': resolución de Sobrecarga fallado." has pasado una Promesa objeto en lugar de una nota. Para el vacío zip es porque setTimeout(fn) se demora fn por algún tiempo más tarde (incluso si el tiempo de espera es 0). Así que cuando esta devolución de llamada fn se llama, en las líneas de abajo ya han sido ejecutados. Y ya que en las líneas de abajo terminen el archivo zip, el archivo zip está siendo creado antes de agregar cualquier archivo a él, yo.e es vacío.
Kaiido

oh, así que setTimeout(fn) empuja el fn para ejecutar la última? Interesante, entonces, ¿cómo puedo hacer un bucle for que tiene un retardo entre cada iteración, sino también a no posponer las llamadas a la final?
absolutenoob

El uso de las Promesas, usted puede tener una mirada en stackoverflow.com/questions/14220321/...
Kaiido

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................