1

I'm trying to create a download button which will allow the user to quickly download all assets in an entries image gallery.

I've started by adding each image url into an array stored in a data attr of the button.

<button data-zip-download='[{% for imageUrl in entry.collectionImages %}"{{imageUrl.url}}"{% if not loop.last %},{% endif %}{% endfor %}]'>Download Gallery</button>

I've then tried to get these URL's using jQuery, and zipping/downloading the zip with JSZip.js and FileSaver.js. Although through a bit of research I think I've found this is generally achieved through PHP.

I'm wondering if anyone on here has had a similar situation and has an idea of how I can achieve this.

I'm not too experienced with ajax but have also read that ajax is necessary to get this working via jQuery.

So far my JavaScript looks as so:

$('[data-zip-download]').each(function(){
var $this = $(this),
    urls = $this.data('zip-download'),
    files = [],
    zip = new JSZip();


for (var i = 0; i < urls.length; i++) {
    files.push(urls[i]);
};

zip.file(files);

$this.on('click', function(){
    zip.generateAsync({type:"blob"}).then(function (blob) { // 1) generate the zip file
        saveAs(blob, "gallery.zip"); // 2) trigger the download
    }, function (err) {
        $this.text(err);
    });
});
});

This however only creates a corrupted zip file as I imagine I need to actually load those images via ajax.

I suppose it would be ideal to simply use a craft/twig function if such a thing exists, although anything that works would be great haha.

Sorry for not having much knowledge on this specific need, really hoping someone out there can help!

Thanks!

2

I would recommend that you do this in php/plugin vs javascript. If you aren't familiar with writing plugins, you can start with the BusinessLogic Plugin — which is a great little plugin template, all set up with example controller, variables, and service file with example actions, methods, etc. Just drop in into your plugins folder, and activate, and you should be good to go.

There are a couple ways to set this up.

  1. Use a form, plugin action, and pass urls or a gallery reference ID in a hidden form input field.

    • set up an HTML form (w/ your download/submit button)
      • add your custom action to your form (i.e. <input type="hidden" name="action" value="businessLogic/downloadZip">
      • add a hidden form input, and encode urls as a comma-separated list, or encode a gallery reference ID (i.e. <input type="hidden" name="galleryid" value="{{ entry.id }}">)
    • add a form action handler to your plugins controller file
      • lookup the urls (if not already provided)
      • generate the zip file and initiate download
  2. Create a custom route, encoded with gallery ID reference

    • add a route to your config/routes.php file
    • set up your route action in your plugin's controller file with the gallery ID encoded as part of the route (i.e. 'downloads/gallery/13')
    • lookup urls using the gallery reference ID, generate zip, and initiate download

The advantage of using a custom route is that you can then just link to it from anywhere, or email the link to your client, without having to use a form. So, I would probably recommend using a route, unless you need to protect access for some reason.

To set up the plugin form action or route handler — have a look at the examples in the BusinessLogic plugin, which provides examples/instructions for both.

To grab the the URLs in your plugin method — you can use crafts built-in methods, as described in the craft docs.

To create the zip — doing a quick google search should come back with some good examples (like this one that has a sample HTML form and the php zip code).

Hopefully that will get you started — let me know if you get stuck, and I might be able to help further.

| improve this answer | |
2

There's actually a Craft CMS 2 plugin that I've used before (with PDFs) that will create a zip from assets: https://github.com/boboldehampsink/zipassets

I'm not 100% sure it would work for your use case, but it should.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.