Multiple download links to one zip file before download javascript
Asked Answered
H

2

10

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?

Hockenberry answered 12/5, 2016 at 2:45 Comment(6)
zip target files at server side and return url after click, then do download via this urlAchievement
What do you mean by "multiple download urls"?Kropotkin
@YinGang but lets say I already have the download links for the files stored in an array. How would i zip those so the user can download the ziped file only?Hockenberry
Ajax the stored array to server side --> server zip files --> return zip url --> request url to download.Achievement
All of the files are at same domain at server?Kropotkin
@gang how would i do those first two steps?Hockenberry
K
12

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

Kropotkin answered 12/5, 2016 at 3:38 Comment(16)
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.Hockenberry
@Hockenberry "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."Kropotkin
Yes but there are ways to work around that, for example downloading this chrome extension: chrome.google.com/webstore/detail/allow-control-allow-origi/… 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.Hockenberry
@Hockenberry "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 <iframe> that when clicked opens an ad? "I'm trying to put a downloaded file from the internet into a zip folder" Yes, what is the URL of the actual resource, .mp3 file, that you want to download?Kropotkin
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^Hockenberry
@Hockenberry "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?Kropotkin
Oh sorry, I guess the url is relative. I'm using the api from this website: youtubeinmp3.com/api try using the json link if you scroll down: www.youtubeinmp3.com/fetch/?format=JSON&video=youtube.com/watch?v=i62Zjga8JOM this returns a link for download to an mp3 file that I want to put in a zipped folder.Hockenberry
@Hockenberry 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.Kropotkin
So is it impossible? or could you download this chrome extension to make it work: chrome.google.com/webstore/detail/allow-control-allow-origi/…Hockenberry
That's really confusing. But for example, trying a different download link with your code, such as replacing "a.html" with "pixabay.com/static/uploads/photo/2016/05/05/02/15/…", the code still doesnt work.Hockenberry
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.Kropotkin
Are there any download links for anything that you can find that actually work?Hockenberry
Have you tried link, above? See also #10143593Kropotkin
@Hockenberry #37176897; see also linked page at previous commentKropotkin
Thanks for all the help haha but still confused a bit. Why can't I use the chrome extension to override the error?Hockenberry
@Hockenberry Perhaps take the time to read all of the possible solutions at linked stackoverflow page? And links from that page #3103319Kropotkin
F
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);

})
Frasch answered 22/8, 2016 at 22:49 Comment(3)
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? dropbox.com/s/0k4e3s79xp6fsap/…Schaffner
I would say debug the Javascript zipFiles method and see what is wrong.Frasch
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 disappearFrasch

© 2022 - 2024 — McMap. All rights reserved.