Adding images from url to a zip file using jsZip
Asked Answered
S

1

7

I am trying to create a zip file using jsZip . The contents of the zip file are images from the web. I have created the following code. But when i run it all am getting is an empty zip file of 22kb.

<html>
<body>
  <script type="text/javascript" src="jszip.js"></script>
  <script type="text/javascript" src="FileSaver.js"></script>
  <script type="text/javascript" src="jszip-utils.min.js"></script>
  <script>
    var imgLinks = ["url1", "url2", "url3"];

    function create_zip() {
      var zip = new JSZip();
      for (var i = 0; i < imgLinks.length; i++) {
        JSZipUtils.getBinaryContent(imgLinks[i], function(err, data) {
          if (err) {
            alert("Problem happened when download img: " + imgLink[i]);
            console.erro("Problem happened when download img: " + imgLink[i]);
            deferred.resolve(zip); // ignore this error: just logging
            // deferred.reject(zip); // or we may fail the download
          } else {
            zip.file("picture" + i + ".jpg", data, {
              binary: true
            });
            deferred.resolve(zip);
          }
        });
      }
      var content = zip.generate({
        type: "blob"
      });
      saveAs(content, "downloadImages.zip");
    }
  </script>
  <br/>
  <br/>
  <center>
    Click the button to generate a ZIP file
    <br/>
    <input id="button" type="button" onclick="create_zip()" value="Create Zip" />
  </center>
</body>
</html>

(url1 , url2 and url3 replaced by image urls i want to download).

Why am i getting these empty zip files?

Splinter answered 2/1, 2015 at 18:45 Comment(2)
do you have the fixed version of this?Subshrub
I just used a CORS proxy . " corsproxy.com/mangacow.co/wp-content/manga/29/172/0002.jpg" .. instead of the direct url i appended it to the free CORS proxy URL, and that solved the problem.Splinter
P
7

JSZipUtils.getBinaryContent is asynchronous : the content will be added after the call to zip.generate(). You should wait for all images before generating the zip file.

Edit :

If the files you are loading are on a different server, this server need to send additional HTTP headers, like Access-Control-Allow-Origin: server-hosting-the-page.com. The Firefox or Chrome debug console will show an error in that case. The js library can't detect a CORS issue (see here) and will trigger a success with an empty content.

Phantasmagoria answered 2/1, 2015 at 23:48 Comment(14)
So how do i check if the images have completed loading, before generating the zip?Splinter
If you are using deferred objects, you can look at this example and the function deferredAddZip here. It uses the jQuery Deferred objects but it should be easy the modify.Phantasmagoria
Than you for your replies. Tried the code and now the zip varies in size with number of files supplied and all the images are present inside the zip file, but all the images are of 0 byte and on opening in image viewer nothing is shown... Any ideas??Splinter
My first idea : check that you wait for the resolution of all the deferred objects before generating the zip ($.when.apply($, deferreds) line 75). Other than that, you can use a debugger (or console.log) to check what contains data (it should be an ArrayBuffer on a recent browser). If you still can't find the issue, I'll need a working code sample :)Phantasmagoria
I tried that same demo code u gave and replaced the file urls with urls to some jpeg files , but the files inside the zip are 0 byte ones, and the zip file varies in size with number of images..Splinter
It looks like a CORS issue. When doing cross site ajax requests, the browser expects the remote file to be served with some headers (Access-Control-Allow-Origin for example). Are you trying to images hosted on a different server than your page ?Phantasmagoria
Then you need to update the server to add HTTP headers (or using the curent server as proxy to download the files), see the update on my answer.Phantasmagoria
So there is no other way around to do this without using the current server as a proxy ?? I was trying to keep everything on the client side , thereby reducing the time required to generate the zip. Currently i am using PHP to do this , the image files are downloaded from the external source to my server , creating a zip in the server and then returning it to the user to download. But it takes too much time as the user have to wait until the images are downloaded to my server from the external source and added to the zip.Splinter
Regardless of the library used, a browser won't allow a cross-site ajax request if the remote server doesn't explicitly allow it. The easiest way is to update the remote server to add some headers. If that's not possible, you will need to find a work-around (using the current server as proxy is the first I though of, you may find other ones).Phantasmagoria
Thank you Very much for all your answers :)Splinter
gogol.6te.net/index.html , thats the demo script i am using and have succesfully found a workaround by using a CORS proxy . Its working fine in firefox, but when used in google chrome i get a "Failed-no file" error.Splinter
It works for me on Firefox / Chromium (linux) and Firefox / Google Chrome (windows), I don't get any error.Phantasmagoria
s14.postimg.org/tm6ykt3g1/chrome_prob.png , this is the sceenshot , My chrome is up to date . OS :windows , checked it on android too and worked fine on both chrome and firefox for android. And btw are you one of the devs of jszip?Splinter
I see 2 errors in your screenshot (the red cross on the right with a "2"), you should check the Console tab. And yes, I'm one of the devs :)Phantasmagoria

© 2022 - 2024 — McMap. All rights reserved.