To be able to have an ACF gallery field automatically generate a zip file of all the images uploaded is a useful feature.

Note: I’ve modified this code to take into account a pre-existing zip file of images, see end of article for this modified code.

Luckily someone has already completed the code. The devs linked blog is no longer active which is unfortunate as he cites a cautionary note in his code comments. His blog post is reproduced below care of the Way Back Machine…

A recent client project for a photographer involved creating protected pages where their clients could download an entire gallery of images as a zip folder. The galleries are dynamic, so I wanted to make the download links dynamic as well, so that every time they added an image to the gallery it would get added to the download without any extra work.

I ended up building out the functionality using a bunch of custom PHP along with an Advanced Custom Fields gallery field to make it happen. As it turned out, we went a different direction for the final build (they wanted granular control over the resolution and a few other things that ended up making it more reasonable to lose the dynamic link).

I thought it’d still be fun to share the code since it seems like a pretty useful utility, so here goes!

Full Code

Let’s just start off with the full code so you can see it all in context. I’ve put a lot of comments throughout to narrate what’s going on and then I’ll point out a few key pieces and features in the breakdown below.

This whole operation can be broken down into three chunks:

  1. Checking the custom field for images
  2. Generating the zip and download link
  3. Displaying the gallery grid

Let’s take them piece by piece:

The custom field check wraps around the rest of the code, since we don’t want to show any of the rest of it if there aren’t images in the gallery, so let’s look at that first.

1. Checking the ACF gallery field for images

I started out by creating an ACF gallery field (part of Advanced Custom Fields PRO) called “Images” The outer frame of the code snippet involves getting the field data and using a conditional to check if the field contains images:

All the code for the download link and gallery itself goes in the commented area (the “yes, field has images” section) and there’s a message to display if no images are found.

2. Generating the zip and download link

The bulk of the code that goes in that comment area is for the zip file generation and the download link.

To start out, I created a variable to hold the download link for the file that will be generated. This is a little tricky – it needs to be a place on the server that is accessible/writeable, so it may take some trial and error to get it right. I used a special /downloads/ directory relative to the root.

The sanitize_title( get_the_title() ) bit uses the gallery page title as the file name, which is a nice little feature to make the file easy to identify after it is downloaded.

Now I can use that variable of $destination to create my file and links throughout the rest of the zip file code.

Next up, there’s a conditional to check if there’s already a zip file in that location. If the file does exist already, we just display the download link, but if not we have to create the file before displaying the link.

Caution: One thing I didn’t get around to testing before we went in a different direction was whether this check causes problems if the gallery is updated. I imagine it would since the file would already exist but with the old set of images.

You may find that you need to add some kind of dynamic text to the file name to make sure it gets updated regularly. The date could work, although you may not want to generate a new zip every day, so maybe use the week number or month or something. Or, potentially something using a cron job to regularly clear out the folder, as discussed in this Stack Overflow thread.

I’m not going to go line by line through generating the zip file since it’s commented in the gist, but the general flow is that you create an array of the gallery files, and then create the zip file from that array of files.

Remember that we’re tying into that ACF gallery field, so if you do this with a different method for inputting your files, you’ll have to change the beginning loop:

In this little snippet, $images is our array from the gallery field, the same variable we used in the very first line of the code where we got the data from that field and checked to be sure there were images in the gallery.

There are a few checks throughout the sequence, making sure that there are files in the array, that each file exists, etc., and then when all is said and done the zip file is created and a download link generated.

3. Displaying the gallery grid

Finally, there’s the on-page gallery display. We’re looping through the gallery field again and spitting out the data into a grid view where the thumbnails are linked to full size images for a lightbox display. This is all ACF syntax for gallery fields, nothing really customized in this bit.

Modified code

The code below takes into account an already existing ZIP file. It counts the number of files in the existing zip and compares this against the actual number of files in the image gallery