如何通过 ajax 获取多个文件并通过 JavaScript 将它们下载为 zip 文件?

How to get multiple files via ajax and download them as a zip file via JavaScript?

是否可以创建一个用 JavaScript(浏览器中的 运行s)编写的仅客户端应用程序,它通过 ajax 获取多个图像文件,然后压缩它们作为 zip(或 tar 或其他)和 returns 它作为文件下载给用户( 没有任何服务器端逻辑 )?

工作流程是这样的:

  1. 在浏览器中打开网站 mydomain.com
  2. 网站通过 ajax 从 mydomain.com/images/image1.pngmydomain.com/images/image2.jpg 收集图像。
  3. 这两个文件现在都自动压缩成存档文件(例如 zip、gzip 或 tar 或其他文件)
  4. 用户在其浏览器中收到此存档文件的通常下载提示。

到目前为止,我认为我可以通过 jQuery:

获得第 1-2 部分 运行ning
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);
    }
  });
}

但是从这里我不知道如何从图像数组创建 zip 文件。我该怎么做?

重要提示: 这必须在所有主流浏览器中 运行,如 IE、Firefox、Chrome、Safari

简答,没有。 JavaScript可以从服务器下载数据,压缩可能是通过一些库实现的(Google很快returns两个结果https://gildas-lormeau.github.io/zip.js and https://stuk.github.io/jszip,后者是一个Node实现),但是执行一个无法从客户端下载。

您将需要某种服务器逻辑,我建议进行一次调用来生成文件和 zip。

天哪!我使用这些库让它工作:

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>

我的script.js

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

// From 
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);
    }
  });
}