Cloudinary Blog

Dynamically generating ZIP files with one line of code

Dynamic ZIP files generation with a single line of code

As a developer, you want to allow your users to download multiple files in a single click. An easy way to download multiple files and share them is to generate a ZIP file. When images are involved, you may also want to normalize the original images before including them in the ZIP file, by scaling them down to the same maximum resolution or converting them to the same format.

In the following simple example, 3 images of cats have been uploaded to the cloud.

fat_cat.jpg fat_cat kitten.jpg kitten hungry_cat.jpg hungry_cat

With one line of code, you can generate a dynamic URL that, for example, automatically creates and then delivers a ZIP file containing the cat images, all scaled down to a width of 200 pixels:

https://api.cloudinary.com/v1_1/demo/image/generate_archive?api_key=373364719177799&expires_at=1557919777&mode=download&public_ids%5B%5D=fat_cat&public_ids%5B%5D=kitten&public_ids%5B%5D=hungry_cat&signature=a2f86b73d32d2a778493d6759d59059d0a30076d&timestamp=1464179836&transformations=c_scale%2Cw_200

The ability to dynamically generate and deliver ZIP files to your users by including one line of code can be useful for developers in a number of ways. For example:

  • Social and messaging apps that allow users to select multiple files to send to another recipient, who subsequently receives all the files in one ZIP file (e.g., the Gmail feature where you can download all attachments as a single ZIP file).
  • Applications that include image galleries and allow users to select multiple images and then download a ZIP file with all the selected images (e.g., as Google Photos has implemented).
  • Allowing your users to download multiple images simultaneously in a single ZIP file, where all the images have been normalized to a certain size, format or quality, (or any other image transformation you want to apply to all the images).

Generating ZIP files of images in the cloud

Cloudinary supports generating ZIP files using the generate_archive Upload API method, which can include any type of file, and offers various options for determining which files to include in the ZIP file (e.g., according to the file's name, all files in the same folder, etc). The method also allows you to apply transformations to all the images before including them in the file and set various options for generating the ZIP file (e.g., naming the file). For more information on all the options available for generating ZIP files, see the generate_archive documentation.

Cloudinary enables you to create and deliver ZIP files in one of the following two ways: * Pre-create the ZIP file and upload it to the cloud. * Generate a dynamic URL for creating and downloading a ZIP file on demand.

The Cloudinary SDKs wrap the generate_archive API method and provide 2 separate methods that accomplish these two goals.

Create a ZIP file of images

To pre-create a ZIP file, use the create_zip SDK method, which also automatically uploads the ZIP file to the cloud, and then gives your users a link for downloading it. This option is best if multiple users will be downloading the resulting ZIP file.

For example, to create a ZIP file called small_cats.zip that contains small (50x50) thumbnails of all of the images in your account that have been tagged as "cats":

Ruby:
Cloudinary::Uploader.create_zip(:tags => 'cats', 
    :resource_type => 'image', :target_public_id => 'small_cats.zip',
    :transformations => {:width => 50, :height => 50, :crop => :fill})
PHP:
\Cloudinary\Uploader::create_zip(array(
    'tags' => 'cats', 'resource_type' => 'image', 
    'target_public_id' => 'small_cats.zip', 'transformations' => array(
        'width' => 50, 'height' => 50, 'crop' => 'fill')));
Python:
cloudinary.uploader.create_zip(
    tags = 'cats', resource_type = 'image', 
    target_public_id = 'small_cats.zip', transformations = {
        width = 50, height = 50, crop => 'fill'})
Node.js:
cloudinary.v2.uploader.create_zip(
    { tags: 'cats', resource_type: 'image', 
    target_public_id: 'small_cats.zip', transformations: {
        width: 50, height: 50, crop: 'fill'}},
    function(error,result) {console.log(result) });
Java:
cloudinary.uploader().createZip(
    ObjectUtils.asMap('tags', 'cats', 'resource_type', 'image',
    'target_public_id', 'small_cats.zip', 'transformations', 
    Arrays.asList(
        new Transformation().width(50).height(50).crop('fill')));
cURL:
curl https://api.cloudinary.com/v1_1/demo/image/generate_archive -X POST --data 'tags=cats$resource_type=image&target_public_id=small_cats.zip&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af&transformations=c_fill%2Cw_50%2Ch_50'

The response to the API call includes all pertinent information about the created zip file, including the URL needed to access it, in this case:

Ruby:
cl_image_tag("small_cats.zip")
PHP:
cl_image_tag("small_cats.zip")
Python:
CloudinaryImage("small_cats.zip").image()
Node.js:
cloudinary.image("small_cats.zip")
Java:
cloudinary.url().imageTag("small_cats.zip");
JS:
cloudinary.imageTag('small_cats.zip').toHtml();
jQuery:
$.cloudinary.image("small_cats.zip")
React:
<Image publicId="small_cats.zip" >

</Image>
Angular:
<cl-image public-id="small_cats.zip" >

</cl-image>
.Net:
cloudinary.Api.UrlImgUp.BuildImageTag("small_cats.zip")
Android:
MediaManager.get().url().resourceType("raw").generate("small_cats.zip");
iOS:
cloudinary.createUrl().setResourceType("raw").generate("small_cats.zip")

Generate a dynamic URL for downloading a ZIP file on demand

Instead of pre-creating the ZIP file, you can generate a signed URL for creating a ZIP file on-the-fly and on-demand with the download_archive_url method of the Utils API. The ZIP file is created and streamed to your user only when the URL is accessed. The resulting ZIP file is not cached or stored in your Cloudinary account, so this option is best if only a single user downloads the resulting ZIP file and avoids waste if the URL is not accessed by the user.

For example, to generate a signed URL for creating and delivering a ZIP file that contains the 'fat_cat' and 'kitten' images:

Ruby:
Cloudinary::Utils.download_zip_url(
    :public_ids => ['fat_cat', 'kitten'], 
    :resource_type => 'image')
PHP:
\Cloudinary\Utils::download_zip_url(
    array(
        'public_ids' => array('fat_cat', 'kitten'), 
        'resource_type' => 'image'));
Python:
cloudinary.utils.download_zip_url(
    public_ids = ['fat_cat', 'kitten'], 
    resource_type = 'image')
Node.js:
cloudinary.v2.utils.download_zip_url(
    { public_ids: ['fat_cat', 'kitten'], resource_type: 'image'},
    function(error,result) {console.log(result) });
Java:
cloudinary.utils().downloadZipUrl(
    ObjectUtils.asMap('public_ids', Arrays.asList('fat_cat', 'kitten'), 
        'resource_type', 'image'));
cURL:
curl https://api.cloudinary.com/v1_1/demo/image/generate_archive -X POST --data 'public_ids[]=fat_cat&public_ids[]=kitten$resource_type=image&mode=download&timestamp=173719931&api_key=436464676&signature=a788d68f86a6f868af'

The API call returns the URL needed to dynamically create and deliver the ZIP file, in this case:

https://api.cloudinary.com/v1_1/demo/image/generate_archive?api_key=373364719177799&expires_at=1557919777&mode=download&public_ids%5B%5D=fat_cat&public_ids%5B%5D=kitten&signature=45411c9ad47e06a2a9468658d919b045d810ec1b&timestamp=1464180350

Dynamic ZIP files with a single line of code

Generating ZIP files with a single line of code allows you to organize, streamline, normalize and optimize multiple image delivery to your users. Either create the ZIP file and upload it to the cloud, or generate a dynamic URL that creates and delivers the ZIP file on demand. For more information on all the options available for generating ZIP files, see the generate_archive documentation. The feature is available for use with all Cloudinary accounts, including the free tier.

Recent Blog Posts

Hipcamp Optimizes Images and Improves Page Load Times With Cloudinary

When creating a website that allows campers to discover great destinations, Hipcamp put a strong emphasis on featuring high-quality images that showcased the list of beautiful locations, regardless of whether users accessed the site on a desktop, tablet, or phone. Since 2015, Hipcamp has relied on Cloudinary’s image management solution to automate cropping and image optimization, enabling instant public delivery of photos, automatic tagging based on content recognition, and faster loading of webpages. In addition, Hipcamp was able to maintain the high standards it holds for the look and feel of its website.

Read more
New Image File Format: FUIF: Why Do We Need a New Image Format

In my last post, I introduced FUIF, a new, free, and universal image format I’ve created. In this post and other follow-up pieces, I will explain the why, what, and how of FUIF.

Even though JPEG is still the most widely-used image file format on the web, it has limitations, especially the subset of the format that has been implemented in browsers and that has, therefore, become the de facto standard. Because JPEG has a relatively verbose header, it cannot be used (at least not as is) for low-quality image placeholders (LQIP), for which you need a budget of a few hundred bytes. JPEG cannot encode alpha channels (transparency); it is restricted to 8 bits per channel; and its entropy coding is no longer state of the art. Also, JPEG is not fully “responsive by design.” There is no easy way to find a file’s truncation offsets and it is limited to a 1:8 downscale (the DC coefficients). If you want to use the same file for an 8K UHD display (7,680 pixels wide) and for a smart watch (320 pixels wide), 1:8 is not enough. And finally, JPEG does not work well with nonphotographic images and cannot do fully lossless compression.

Read more
 New Image File Format: FUIF:Lossy, Lossless, and Free

I've been working to create a new image format, which I'm calling FUIF, or Free Universal Image Format. That’s a rather pretentious name, I know. But I couldn’t call it the Free Lossy Image Format (FLIF) because that acronym is not available any more (see below) and FUIF can do lossless, too, so it wouldn’t be accurate either.

Read more
Optimizing Video Streaming and Delivery: Q&A with Doug Sillars

Doug Sillars, a digital nomad and a freelance mobile-performance expert, answers questions about video streaming and delivery, website optimization, and more.

Doug Sillars, a freelance mobile-performance expert and developer advocate, is a Google Developer Expert and the author of O’Reilly’s High Performance Android Apps. Given his extensive travels across the globe—from the UK to Siberia—with his wife, kids, and 11-year-old dog, Max, he has been referred to as a “digital nomad.” So far in 2018, Doug has spoken at more than 75 meetups and conferences!

Read more