2013-07-07 28 views
6

Sto usando la libreria javascript zip.js. Ho cercato tutto intorno a Non riesco a trovare un esempio in cui più di un file viene aggiunto allo zip.Come aggiungere più file a un file zip con zip.js?

Ecco il mio codice, ma genera un zip "danneggiato".

var len = results.rows.length, i; 
var k=1; 
zip.createWriter(new zip.BlobWriter(), function(writer) { 
    for (i = 0; i < len; i++){ 
     // get the image url from a sqlite request 
     url = results.rows.item(i).url; 


     var img = new Image(); 
     img.onload = function() { 
      var a = document.createElement('a'); 
      a.href = this.src; 
      var filename= a.pathname.split('/').pop(); // filename.php 
      timest = new Date().getTime(); 
      // use a TextReader to read the String to add 

       writer.add(timest+".jpg", new zip.Data64URIReader(getBase64Image(img)), function() { 
       // onsuccess callback 
        k++; 
        if(k==len){ 
         setTimeout(function(){ 
         writer.close(function(blob) { 

          // blob contains the zip file as a Blob object 
          $('#test').attr("href", window.URL.createObjectURL(blob)); 
          $('#test').attr("download", "woeii.zip"); 

         }); 
         },1000); 
        } 
       }, function(currentIndex, totalIndex) { 
       // onprogress callback 
       }); 



     }; 
     img.src = url; 
    } 
}); 

Qualche idea per farlo funzionare? :)

risposta

6

Se si sta cercando un buon esempio di codice che gestisce più file, see here. È quindi possibile view the source code.

Questa è la fonte chiave della demo (modificato solo leggermente):

var obj = this; 
var model = (function() { 
    var zipFileEntry, zipWriter, writer, creationMethod, URL = obj.webkitURL || obj.mozURL || obj.URL; 

    return { 
     setCreationMethod : function(method) { 
      creationMethod = method; 
     }, 
     addFiles : function addFiles(files, oninit, onadd, onprogress, onend) { 
      var addIndex = 0; 

      function nextFile() { 
       var file = files[addIndex]; 
       onadd(file); 
       // Modified here to use the Data64URIReader instead of BlobReader 
       zipWriter.add(file.name, new zip.Data64URIReader(file.data), function() { 
        addIndex++; 
        if (addIndex < files.length) 
         nextFile(); 
        else 
         onend(); 
       }, onprogress); 
      } 

      function createZipWriter() { 
       zip.createWriter(writer, function(writer) { 
        zipWriter = writer; 
        oninit(); 
        nextFile(); 
       }, onerror); 
      } 

      if (zipWriter) 
       nextFile(); 
      else if (creationMethod == "Blob") { 
       writer = new zip.BlobWriter(); 
       createZipWriter(); 
      } else { 
       createTempFile(function(fileEntry) { 
        zipFileEntry = fileEntry; 
        writer = new zip.FileWriter(zipFileEntry); 
        createZipWriter(); 
       }); 
      } 
     }, 
     getBlobURL : function(callback) { 
      zipWriter.close(function(blob) { 
       var blobURL = creationMethod == "Blob" ? URL.createObjectURL(blob) : zipFileEntry.toURL(); 
       callback(blobURL); 
       zipWriter = null; 
      }); 
     }, 
     getBlob : function(callback) { 
      zipWriter.close(callback); 
     } 
    }; 
})(); 

Usage: assume un elemento <a id="downloadLink">Download</a> esiste per fornire il download una volta pronto.

// Prepare your images 
var files = []; 
for (i = 0; i < len; i++) { 

    // Get the image URL from a SQLite request 
    var url = results.rows.item(i).url; 

    (function(url){ 
     var img = new Image(); 
     img.onload = function() { 
      // Add to file array [{name, data}] 
      var a = document.createElement('a'); 
      a.href = this.src; 
      var filename= a.pathname.split('/').pop(); 

      console.log("Loaded file " + filename); 
      files.push({name: filename, data: getBase64Image(img) }); 
     } 
     img.src = url; 
    })(url); 
} 

// Wait for the image to load 
var check = setInterval(function(){ 
    if(files.length==images.length) { 
     clearInterval(check); 

     // Set the mode 
     model.setCreationMethod("Blob"); 

     // Add the files to the zip 
     model.addFiles(files, 
      function() { 
       // Initialise Method 
       console.log("Initialise"); 
      }, function(file) { 
       // OnAdd 
       console.log("Added file"); 
      }, function(current, total) { 
       // OnProgress 
       console.log("%s %s", current, total); 
      }, function() { 
       // OnEnd 
       // The zip is ready prepare download link 
       // <a id="downloadLink" href="blob:url">Download Zip</a> 
       model.getBlobURL(function(url) { 
        document.getElementById("downloadLink").href = url; 
        document.getElementById("downloadLink").style.display = "block"; 
        document.getElementById("downloadLink").download = "filename.zip"; 
       }); 
      }); 

    } 
}, 500); 

È possibile utilizzare il codice sorgente di esempio per aggiungere indicatori in corso. Spero che questo aiuti, la cosa bella di questo metodo è che il modello zip è facilmente riutilizzabile se lo si fa è il proprio file JS.


Un altro pensiero: Presumo che si sta utilizzando la funzione from heregetBase64Image, in caso affermativo e si verificano ancora problemi di corruzione, forse provare a modificare il ritorno al semplice return dataURL; e commentare la .replace(..., come il Data64URIReader può aspettare il prefisso .

+0

Thx! :) questo sembra funzionare. Ho un ultimo problema, solo l'ultima immagine viene salvata più volte nello zip. Penso che derivi dalla funzione del modello. Ci sto guardando. –

+0

Ho apportato una modifica al codice pochi minuti fa che potresti non aver ottenuto. Nel caricatore di immagini assicurati che vi sia 'var' davanti all'URL o la funzione' onload' non rilevi la variabile correttamente. – Scott

+0

Fammi sapere se hai bisogno di ulteriore aiuto. – Scott

2

Ecco una versione ridotta di that demo che utilizza solo la memoria RAM. Presuppone che zip.js, z-worker.js e deflate.js dall'installazione zip.js siano nella stessa directory dei due file sottostanti, insieme a FileSaver.js.

Nota: Questo non è un codice pronto per la produzione! È una demo di ossa nude che ho fatto in modo da poter capire cosa stava succedendo. Se si genera e si salva lo zip a livello di codice, potrebbe essere necessario implementare un iteratore nextFile() come quello sopra per evitare che una condizione di competizione compili il zip con file vuoti. (Vedere https://stackoverflow.com/a/29738675/738675 per un esempio di questo.)

demo.html:

<li> 
    add files into the zip 
    <input type="file" multiple id="file-input" onchange="addFiles(this.files)"> 
</li> 
<li> 
    download the zip file 
    <a href="#" onclick="saveZip()">Download</a> 
</li> 

<script type="text/javascript" src="zip.js"></script> 
<script type="text/javascript" src="demo.js"></script> 
<script type="text/javascript" src="FileSaver.js"></script> 

demo.js:

var zipWriter; 

function addFiles(files) { 
    writer = new zip.BlobWriter(); 
    zip.createWriter(writer, function(writer) { 
     zipWriter = writer; 
     for (var f = 0; f < files.length; f++) { 
      zipWriter.add(files[f].name, 
      new zip.BlobReader(files[f]), function() {}); 
     } 
    }); 
} 

function saveZip() { 
    zipWriter.close(function(blob) { 
     saveAs(blob, "Example.zip"); // uses FileSaver.js 
     document.getElementById("file-input").value = null; // reset input file list 
     zipWriter = null; 
    }); 
} 
Problemi correlati