Perché FileSaver saveAs non funziona con un JSZip?

0

Domanda

Primo tempo distacco, questo è tutto il codice (la maggior parte di esso che ho trovato online e modificato alcune cose per servire il mio scopo), ma, più specificamente, il mio errore è verso la fine, quando mi arriva.

Uncaught TypeError: Impossibile eseguire l' 'createObjectURL' su 'URL': la risoluzione dell'Overload non riuscita.

Quando ho semplicemente utilizzare saveAs(img_url, "img.png"), l'opzione di salvataggio del computer portatile di pop up. Ma mi da l'errore che ho citato sopra quando si tenta di utilizzare il "contenuto". Ho filesaver e jszip nello script, io proprio non riesco a trovare alcun modo per correggere l'errore, che poi si interrompe l'esecuzione di qualcosa di più. Mi dispiace per il codice disordinato, sarebbe davvero apprezzare aiuto.

La parte principale è verso il basso, per il resto c'è solo in caso che qualcuno potrebbe voler vedere. C'è l'url di blob poi la tela generatore, solo che non so perché non si salva.

!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

Migliore risposta

1

zip.gzip.generateAsync() restituisce una Promessa. Questa la Promessa di risolvere con un Blob, qualche tempo dopo, ma è una Promessa, non un Blob.
Quindi è necessario attendere la risoluzione di questa Promessa di accesso generato Blob.

È possibile contrassegnare la funzione come async e poi utilizzare il await parola chiave:

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

O avvolgere la saveAs parte un callback passato alla Promessa .then():

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

Ora, ciò che si sceglie, il vostro file zip sarà effettivamente vuota. Aggiungere il contenuto solo nel callback di setTimeout, il che significa che il contenuto è aggiunto solo dopo che hai fatto creare il file zip, che è troppo tardi.
Quindi, rimuovere l' setTimeout( parte che sembra inutile e di eseguire la richiamata contenuto direttamente.

2021-11-21 23:32:28

Io avevo usato il setTimeout per aggiungere un ritardo quando visivamente vedere il cambiamento attraverso i colori in modo casuale sulla pagina HTML. Cercherò che, sebbene come mai la zip sarebbe vuota? Ma suppongo che da quando ho inizializzare la zip non appena il pulsante viene cliccato, quindi all'interno del ciclo sto aggiungere file alla cartella zip?
absolutenoob

Wow, questo ha funzionato, vi ringrazio molto. Se si potesse, si potrebbe forse spiegare perché in particolare che è stato il problema?
absolutenoob

Il problema che causava "Uncaught TypeError: Impossibile eseguire l' 'createObjectURL' su 'URL': la risoluzione dell'Overload non riuscita." si passò una Promessa oggetto invece di un Blob. Per il vuoto zip è perché setTimeout(fn) ritardo fn per qualche tempo dopo (anche se il timeout è 0). Così, quando questo callback fn si chiama, le linee di seguito, sono stati già eseguiti. E poiché, secondo le linee di seguito definirete il file zip, il file zip è stato creato prima dell'aggiunta di qualsiasi file io.e è vuoto.
Kaiido

oh, così setTimeout(fn) spinge fn per eseguire l'ultima? Interessante, quindi come faccio a fare un ciclo for che ha un ritardo tra ogni iterazione, ma anche di non rimandare le chiamate alla fine?
absolutenoob

Utilizzare Promesse, si può avere uno sguardo a stackoverflow.com/questions/14220321/...
Kaiido

In altre lingue

Questa pagina è in altre lingue

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