Download many files by automatically generated ZIP file

Acclaim/Blog/Snippets/Download many files by automatically generated ZIP file
  • Comments icon
    0 comments
  • 4 minutes of reading
  • 519 views
Share

Learn how to download many files by automatically generating ZIP files. The ZIP file is a compressed archive of one or more files. Compressing and archiving these files in this way allows for faster transfer and easier storage.

Downloading ZIP files

Table Of Contents

If you make various files on the website downloadable, you may also want to prepare a ZIP file containing all the items. Such a ZIP file is generated dynamically by PHP. Thanks to this, we do not have to ask the client to add a separate zip file, because we can generate it automatically. This can be very practical, especially when a client selects particular files that he or she would like to download. This way, the appropriate package will be prepared each time.

Download many files at once

Depending on your situation, you can prepare this in several ways. I will show you how to download all the files using JavaScript and using PHP.

JavaScript version

First of all, you need to install and import 👉 this package 👈

npm install jszip

Now in the file where you want to have that functionality, you need to import the installed package:

import JSZip from "jszip";

Finally, when we have all the necessary resources, we can start to work with the code. In my case, I have to select multiple files via checkboxes. Then the user needs to click the “Download” button. However, I also need to allow users to download a single file, by clicking on the file name. But let me focus on a multiple files download option. First of all, we need to store all links that we want to download files from into an array. Actually, we can go through DOM and find all the checked checkboxes along with finding the anchor sibling elements to get URLs. Let me show you a simpler version:

const urls = [
    "https://example.com/file1.txt", 
    "https://example.com/file2.txt", 
    "https://example.com/file3.txt"
];

As long as we have an array with the proper structure we can use that function to generate a ZIP file.

const saveZip = (filename, urls) => {
    if(!urls) return;

    const zip = new JSZip();
    const folder = zip.folder("files"); // folder name where all files will be placed in 

    urls.forEach((url) => {
        const blobPromise = fetch(url).then((r) => {
            if (r.status === 200) return r.blob();
            return Promise.reject(new Error(r.statusText));
        });
        const name = url.substring(url.lastIndexOf("/") + 1);
        folder.file(name, blobPromise);
    });

    zip.generateAsync({ type: "blob" }).then((blob) => saveAs(blob, filename));

};

Now it’s time to use that function – let me go back to the urls in an array. It cannot be easier than this:

const urls = [
    "https://example.com/file1.txt", 
    "https://example.com/file2.txt", 
    "https://example.com/file3.txt"
];

saveZip("my_project_files_to_download.zip", urls);

And that’s it – when you attach that function to some button – the script automatically creates a ZIP file. The ZIP file can be downloaded by the user like a normal (statically served) file.

PHP version

Let’s prepare the variables that we will reuse in the code:

$sanitized_title = sanitize_title( $name ) 
$destination = "downloads/file-{$sanitized_title}.zip";

$zip = new ZipArchive();

Make sure that we can create a file in the given path:

if (!$error = $zip->open($destination, ZipArchive::CREATE)) {
        exit("Cannot create file in specified path: {$destination}, because of following error: {$error}}");
    }

Check if such a file does not already exist:

if ( file_exists( $destination ) ) return esc_url( home_url( '/' ) ) . $destination;

Create a zip file in the specified path:

// Create file
$zip->open( $destination, ZipArchive::CREATE );

Prepare the paths to the files you want to go into the zip file. In my case I’m pulling data from wordpress using advanced custom field plugin:

// Get files path;s from WordPress Custom Field 
$acf_files_repeater_field = get_field("acf_files_repeater_field");

// Push files into zip archive 
if($acf_files_repeater_field) {
    foreach($acf_files_repeater_field as $file_row) {
        if(isset($file_row['file'])) {
            $file = get_attached_file( $file_row['file']['id']);
            
            if(!$file) return;

            $new_filename = substr($file,strrpos($file,'/') + 1);
            $zip->addFile( $file, $new_filename );
        }
    }
}

Later, you just need to concatenate everything together and return the path to the created zip file

$zip->close();

// return url to zip
$zip_download = esc_url( home_url( '/' ) ) . $destination;

And that’s the whole code:

function process_zip($name) {
    // Define file path and name
    $sanitized_title = sanitize_title( $name ) 
    $destination = "downloads/file-{$sanitized_title}.zip";
    $zip = new ZipArchive();

    if (!$error = $zip->open($destination, ZipArchive::CREATE)) {
        exit("Cannot create file in specified path: {$destination}, because of following error: {$error}}");
    }

    if ( file_exists( $destination ) ) return esc_url( home_url( '/' ) ) . $destination;
        
    // Create file
    $zip->open( $destination, ZipArchive::CREATE );

    // Get files path;s from WordPress Custom Field 
    $acf_files_repeater_field = get_field("acf_files_repeater_field");

    // Push files into zip archive 
    if($acf_files_repeater_field) {
        foreach($acf_files_repeater_field as $file_row) {
            if(isset($file_row['file'])) {
                $file = get_attached_file( $file_row['file']['id']);
                
                if(!$file) return;
                 
                $new_filename = substr($file,strrpos($file,'/') + 1);
                $zip->addFile( $file, $new_filename );
            }
        }
    }

    $zip->close();

    // return url to zip
    return = esc_url( home_url( '/' ) ) . $destination;

}

Related articles

Comments

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.