9

Is it possible, in javascript, to have multiple download urls sent into one zip file and that zip file can be downloaded. So pretty much, on my web page, there is one button, that when clicked downloads a zip file of all the files from the download urls compressed into the zip?

I believe I'd need to use jszip or some tool like that. Is this at all possible and is there any advice on where to start?

Dude1310
  • 127
  • 2
  • 3
  • 9

2 Answers2

11

You can use JSZip.js, XMLHttpRequest(), Array.prototype.map() , Promise.all() to create .zip file when all requests for files have completed; use <a> element with download attribute set to objectURL of .zip file at JSZip .generateAsync() function, click on a element should display Save File dialog with created .zip as downloadable file.

<head>
  <script src="jszip.js"></script>
  <script>
    window.onload = function() {
      var zip = new JSZip();
      var a = document.querySelector("a");
      var urls = ["a.html", "b.html"];

      function request(url) {
        return new Promise(function(resolve) {
          var httpRequest = new XMLHttpRequest();
          httpRequest.open("GET", url);
          httpRequest.onload = function() {
            zip.file(url, this.responseText);
            resolve()
          }
          httpRequest.send()
        })
      }

      Promise.all(urls.map(function(url) {
          return request(url)
        }))
        .then(function() {
          console.log(zip);
          zip.generateAsync({
              type: "blob"
          })
          .then(function(content) {
            a.download = "folder" + new Date().getTime();
            a.href = URL.createObjectURL(content);
            a.innerHTML = "download " + a.download;
          });
        })
    }
  </script>
</head>

<body>
  <a href="" download>download</a>
</body>

plnkr http://plnkr.co/edit/baPtkILg927DtJfh4b5Y?p=preview

guest271314
  • 1
  • 15
  • 104
  • 177
  • That doesn't work for urls needed to be downloaded. That only works if you have the html files in the same folder. Suppose I have this download link: https:\/\/www.youtubeinmp3.com\/download\/get\/?i=trShzDCP0ESQ5bFdcMpe8y6H6WJvxYLXMa7OtmJMeO%2BfxY1E1Rx5FQwsWk%2BDS9fEoIXCo8QboB0dX6%2FP0e2rJw%3D%3D I want one button that when clicked will put these downloads into one zipped folder. When I change a.html to the link I provided, it no longer works. – Dude1310 May 12 '16 at 12:50
  • @Dude1310 _"When I change a.html to the link I provided, it no longer works. "_ The URL does not have `Access-Control-Allow-Origin` header set _"`XMLHttpRequest cannot load https://www.youtubeinmp3.com/download/?video=https://www.youtube.com/watch?v=i62Zjga8JOM. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://stackoverflow.com' is therefore not allowed access.`"_ – guest271314 May 12 '16 at 13:21
  • Yes but there are ways to work around that, for example downloading this chrome extension: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en and even after I download that, replacing a.html with the download link for the mp3 file I provided won't work because it gives an error stating that they could not find the location of the mp3 file because your code only downloads files that you have saved already, I'm trying to put a downloaded file from the internet into a zip folder. – Dude1310 May 12 '16 at 13:26
  • @Dude1310 _"with the download link for the mp3 file I provided won't work because it gives an error stating that they could not find the location of the mp3 file"_ Not certain where `.mp3` actual location is? The "Download" window appears to be an ` – guest271314 May 12 '16 at 13:34
  • If you press this link: https:\/\/www.youtubeinmp3.com\/download\/get\/?i=trShzDCP0ESQ5bFdcMpe8y6H6WJvxYLXMa7OtmJMeO%2FqhE5HNe6etvXNYLqsXm5HkScdBuZ%2BJgrHtb%2FWohCaWg%3D%3D a download will start right away for an mp3 file. Instead of downloading that mp3 file, i want to put it into a zip with other mp3 files for download. i'm using an api to get the mp3 files from youtube. Try going to that link^ – Dude1310 May 12 '16 at 13:37
  • @Dude1310 _"No Video Was Found"_ You probably could unescape URL? How would link at another page be clicked using `XMLHttpRequest()`? What is the direct link to resource? _" i'm using an api to get the mp3 files from youtube"_ Link to API documentation? Or is only approach available clicking download link at page? – guest271314 May 12 '16 at 13:39
  • Oh sorry, I guess the url is relative. I'm using the api from this website: https://www.youtubeinmp3.com/api/ try using the json link if you scroll down: www.youtubeinmp3.com/fetch/?format=JSON&video=http://www.youtube.com/watch?v=i62Zjga8JOM this returns a link for download to an mp3 file that I want to put in a zipped folder. – Dude1310 May 12 '16 at 13:42
  • @Dude1310 `XMLHttpRequest cannot load http://www.youtubeinmp3.com/download/get/?i=Hes1wwZTx03diwb8wuslSc9mm49DGyGQYnbaQZoJuNdlQ6Ago%2BN4LvUUQA5qBs43gzh1APL5HkzCAquh%2Fzceaw%3D%3D. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://stackoverflow.com' is therefore not allowed access.` – guest271314 May 12 '16 at 13:51
  • So is it impossible? or could you download this chrome extension to make it work: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en – Dude1310 May 12 '16 at 13:54
  • That's really confusing. But for example, trying a different download link with your code, such as replacing "a.html" with "https://pixabay.com/static/uploads/photo/2016/05/05/02/15/gecko-1373144_640.jpg?attachment", the code still doesnt work. – Dude1310 May 12 '16 at 14:01
  • Same result `XMLHttpRequest cannot load https://pixabay.com/static/uploads/photo/2016/05/05/02/15/gecko-1373144_640.jpg?attachment%22. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://stackoverflow.com' is therefore not allowed access.` – guest271314 May 12 '16 at 14:03
  • Are there any download links for anything that you can find that actually work? – Dude1310 May 12 '16 at 14:04
  • Have you tried link, above? See also http://stackoverflow.com/questions/10143093/origin-is-not-allowed-by-access-control-allow-origin – guest271314 May 12 '16 at 14:05
  • @Dude1310 http://stackoverflow.com/questions/37176397/multiple-download-links-to-one-zip-file-before-download-javascript/37176830?noredirect=1#comment61910769_37176830; see also linked page at previous comment – guest271314 May 12 '16 at 14:07
  • Thanks for all the help haha but still confused a bit. Why can't I use the chrome extension to override the error? – Dude1310 May 12 '16 at 14:16
  • @Dude1310 Perhaps take the time to read all of the possible solutions at linked stackoverflow page? And links from that page http://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome – guest271314 May 12 '16 at 14:23
2

I recently had to solve the same issue and had found a solution using JSZipUtils.

The solution can be found here http://plnkr.co/edit/vWARo0dXbkgzmjyoRNi0?p=preview

I have two files that I would like to zip and download via the users browser and I call the function getBinaryContent(path, callback) on both files. The path here is the where the file is stored.

The two files are a .wav file and a .json file. Each of them should be treated differenly and hence you should use {base64:true,binary:true} for the .wav file and {binary:true} for the json file as an argument for the function file of JSZip.

The code can be found here as well

var file_confirmation=[false,false];
var file_name=["test1.wav","test.json"];
var urlList =["test.wav","test.json"];

var filenameSave ="myZip";


function zipFiles(id,urls)
{
    zip = new JSZip();

JSZipUtils.getBinaryContent(urls[0],function (err, data) 
{
    if(!err)
    {
        var dic={base64:true,binary:true}; //WAV File Encoding
        zip.file(file_name[0], data, dic);
        file_confirmation[0]=true;
        downloadZipIfAllReady(id);
    }
});

JSZipUtils.getBinaryContent(urls[1],function (err, data) 
    {
        if(!err)
        {
            var dic={binary:true}; //JSON File Encoding
            zip.file(file_name[1], data, dic);
            file_confirmation[1]=true;
            downloadZipIfAllReady(id);
        }
    });
}    

function downloadZipIfAllReady(id)
    {
        if(file_confirmation.every(function(element, index, array) {return element;}))
        {
             zip.generateAsync({type:"blob"})
                .then(function(content)
                {
                  var a = document.querySelector("#"+id);
                  a.download = filenameSave;
                  a.href = URL.createObjectURL(content);
                  a.click();
            });
    }
}


$(document).ready(function()
{

 zipFiles("a_id",urlList);

})
M.C.
  • 1,765
  • 3
  • 29
  • 31
  • when i download your example as a zip file and run the index file off my computer nothing happens, would you know of any reason for this? https://www.dropbox.com/s/0k4e3s79xp6fsap/Screenshot%202017-01-15%2016.55.20.png?dl=0 – Nick Garver Jan 15 '17 at 21:54
  • I would say debug the Javascript zipFiles method and see what is wrong. – M.C. Jan 15 '17 at 22:18
  • The problem is your accessing the link with file://: .. You should instead install a local server (like XAMPP) and open locally using localhost/..../index.html and then the cross origin error will disappear – M.C. Jan 17 '17 at 13:10