2

Would it be possible to create a client-site only application written in JavaScript (that runs in a browser) which gets multiple image files via ajax, then compresses them as zip (or tar or whatever) and returns it to the user as a file download (without any server-side logic)?

Workflow would be like this:

  1. Open website mydomain.com in a browser
  2. Website collects images from mydomain.com/images/image1.png and mydomain.com/images/image2.jpg via ajax.
  3. Both files are now automatically compressed into an archive file (e.g. zip, gzip or tar or whatever)
  4. User gets the usual download prompt for his browser for this archive file.

So far I think I can get part 1-2 running via jQuery:

var urls = [
  'image1.png',
  'image2.jpg'
];
var images = [];
var counter = 0;

function createArchive(images){
  // How to implement this?
}

function download(archive){
  // How to implement this?
}

for (var i = 0; i<urls.length; i++) {
  $.ajax('images/' + urls[i]).done(function(data) {
    images.push(data);
    counter++;

    // Offer download of archive when all ajax calls are done
    if (counter == urls.length){
      var archive = createArchive(images);
      download(archive);
    }
  });
}

But from here I don't know how to create the zip file from the images array. How would I do that?

Important: This has to run in all majors browsers like IE, Firefox, Chrome, Safari

Timo Ernst
  • 15,243
  • 23
  • 104
  • 165

2 Answers2

3

Holy moly! I got it to work using these libs:

HTML

<!doctype html>

<html>

  <head>
    <title>Zipper</title>
    <script src="jszip.min.js"></script>
    <script src="FileSaver.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body>

  </body>

</html>

My script.js

var urls = [
  'yufegi.jpg',
  'duck.jpg'
];
var images = [];
var counter = 0;

// From http://stackoverflow.com/questions/6150289/how-to-convert-image-into-base64-string-using-javascript
function convertImgToBase64URL(url, callback, outputFormat){
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
      var canvas = document.createElement('CANVAS'),
      ctx = canvas.getContext('2d'), dataURL;
      canvas.height = this.height;
      canvas.width = this.width;
      ctx.drawImage(this, 0, 0);
      dataURL = canvas.toDataURL(outputFormat);
      callback(dataURL, url);
      canvas = null;
    };
    img.src = url;
}

function createArchive(images){
  // Use jszip
  var zip = new JSZip();
  var img = zip.folder("images");
  for (var i=0; i<images.length; i++) {
    img.file(images[i].url, images[i].data, {base64: true});  
  }
  var content = zip.generate({type:"blob"});

  // Use FileSaver.js
  saveAs(content, "images.zip");
}

for (var i = 0; i<urls.length; i++) {
  convertImgToBase64URL(urls[i], function (base64Img, url) {
    images.push({
      url: url,
      data: base64Img
    });
    counter++;
    if (counter == urls.length) {
      createArchive(images);
    }
  });
}
Timo Ernst
  • 15,243
  • 23
  • 104
  • 165
0

Short answer, no. JavaScript can download data from the server and zipping might be achieved by some library (Google quickly returns two results https://gildas-lormeau.github.io/zip.js and https://stuk.github.io/jszip, the latter is a Node implementation), but executing a download from the client-side is not possible.

You will have to have some sort of server logic and I'd recommend having one call that will produce the files and zip.

Or Barmatz
  • 307
  • 3
  • 8