Download all files in a folder from Supabase storage as a ZIP file with Next.js

In this article we'll look at how to download all files in a folder from Supabase storage as a ZIP file with Next.js.

By default, Supabase doesn't provide a way to download all files in a folder using the download method.

So the only way to do this is to download each file individually and then zip them up.

Let's assume you have a folder called images in your Supabase storage bucket my-bucket and you want to download all the files in that folder.

First, we'll need to get a list of all the files in the folder.

We can do this by using the list method on the storage object.

import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';

const supabaseClient = createClientComponentClient();

const bucket = "my-bucket";
const folder = "images";

// Get a list of all the files in the path /my-bucket/images
const { data: files, error } = await supabaseClient.storage
  .from(bucket)
  .list(folder);

if (error) {
  throw error;
}

// If there are no files in the folder, throw an error
if (!files || !files.length) {
  throw new Error("No files to download");
}

Once we have a list of all the files in the folder, we can download each file individually.

const promises = [];

// Download each file in the folder
files.forEach((file) => {
  promises.push(
    supabaseClient.storage.from(bucket).download(`${folder}/${file.name}`)
  );
});

// Wait for all the files to download
const response = await Promise.allSettled(promises);

// Map the response to an array of objects containing the file name and blob
const downloadedFiles = response.map((result, index) => {
  if (result.status === "fulfilled") {
    return {
      name: files[index].name,
      blob: result.value.data,
    };
  }
});

We'll need to install the @zip.js/zip.js package to create the zip file.

npm install @zip.js/zip.js

Make sure you import the BlobReader, BlobWriter and ZipWriter classes your file.

import { BlobReader, BlobWriter, ZipWriter } from "@zip.js/zip.js";

Now that we have an array of objects containing the file name and blob, we can zip them up and download them.

// Create a new zip file
const zipFileWriter = new BlobWriter("application/zip");
const zipWriter = new ZipWriter(zipFileWriter, { bufferedWrite: true });

// Add each file to the zip file
downloadedFiles.forEach((downloadedFile) => {
  if (downloadedFile) {
    zipWriter.add(downloadedFile.name, new BlobReader(downloadedFile.blob));
  }
});

// Download the zip file
const url = URL.createObjectURL(await zipWriter.close());
const link = document.createElement("a");

link.href = url;
link.setAttribute("download", "documents.zip");

document.body.appendChild(link);

link.click();