Eazip
Guides

Download All Firebase Storage Files as a ZIP

List a Cloud Storage for Firebase folder, turn the files into a ZIP in the browser, and scale past tab limits with Eazip Cloud.

Firebase Storage has no built-in ZIP export. To let a user download a whole folder as one file, list the objects, get a URL for each one, and pass those URLs to Eazip. You can do this entirely with the client Web SDK, or generate signed URLs on a server for private files.

Loading live demo…

Client-only: list and zip with the Web SDK

If your Security Rules already allow the signed-in user to read a folder, you do not need a server at all. listAll() returns every item under a path, and getDownloadURL() returns a browser-fetchable URL with an access token embedded:

import { getStorage, ref, listAll, getDownloadURL } from 'firebase/storage';
import { createZip } from '@eazip/core';

const storage = getStorage();
const folderRef = ref(storage, `exports/${userId}`);

const { items } = await listAll(folderRef);

const files = await Promise.all(
  items.map(async (itemRef) => ({
    url: await getDownloadURL(itemRef),
    filename: itemRef.name,
  })),
);

const result = await createZip({
  files,
  zipName: 'export.zip',
});

result.download();

listAll() buffers the whole listing in memory, so it fits a single folder of files rather than a bucket-wide crawl. For a deeply nested path, call listAll() on each prefixes entry to walk subfolders, and build a filename that keeps the folder structure, for example ${folderPath}/${itemRef.name}.

Firebase Storage download URLs point at firebasestorage.googleapis.com, which returns CORS headers that allow a browser fetch(), so this works as a Local job with no extra configuration.

Server-signed URLs with the Admin SDK

Use a server when files are private, when only an authorized backend should decide which objects a user may export, or when you want a single endpoint instead of relying on Security Rules for every read. The Admin SDK's bucket is a @google-cloud/storage bucket, so you can list by prefix and sign each object directly:

// server
import { getStorage } from 'firebase-admin/storage';

export async function getExportFiles(uid: string) {
  const bucket = getStorage().bucket();
  const [objects] = await bucket.getFiles({ prefix: `exports/${uid}/` });

  return Promise.all(
    objects.map(async (file) => {
      const [url] = await file.getSignedUrl({
        action: 'read',
        expires: Date.now() + 15 * 60 * 1000,
      });

      return { url, filename: file.name.split('/').pop()! };
    }),
  );
}
// browser
import { createZip } from '@eazip/core';

const response = await fetch('/api/exports/files', { credentials: 'include' });
const files = (await response.json()) as { url: string; filename: string }[];

const result = await createZip({
  files,
  zipName: 'export.zip',
});

result.download();

Never send a Firebase Admin service account key or an unscoped bucket credential to the browser. The endpoint should authenticate the request, authorize the specific prefix or object list, and return only { url, filename } entries. Signed GCS URLs allow browser GETs by default; if you serve objects through a custom domain in front of the bucket, confirm that domain also returns CORS headers, or configure them with gcloud storage buckets update --cors-file.

When to use Eazip Cloud

Local jobs cover most exports, but switch to strategy: 'cloud' when:

  • the folder has thousands of files or the archive would be multi-gigabyte;
  • signed URLs may expire before a slow connection finishes fetching them all;
  • the export should keep running if the user closes the tab or reloads; or
  • you would rather not hold every object's bytes in browser tab memory.
const result = await createZip({
  strategy: 'cloud',
  publicKey: 'pk_ez_...',
  files,
  zipName: 'export.zip',
});

result.downloadAll();

Add firebasestorage.googleapis.com (or your custom domain) to the Public App's allowed source hosts, and give signed URLs enough lifetime for Eazip Cloud to start and finish reading them. Eazip Cloud usage is metered, and Cloud Storage still bills its own bandwidth for the source fetches — "zero egress" here means Eazip does not add a separate outbound-bandwidth fee on top of that.

Limits and alternatives

For a handful of files, looping getDownloadURL() and triggering one download per file is simpler than a ZIP and needs no extra dependency. A Cloud Function that zips objects server-side works for small exports, but you own its memory and timeout limits, and every added file grows both; Eazip Cloud is built for that job instead. On the Spark plan, watch Cloud Storage's free bandwidth quota — a folder-wide export can consume it quickly, and Blaze bills download bandwidth per GB regardless of whether Eazip or a Cloud Function reads the objects.

FAQ

Can I download a whole folder from Firebase Storage?

Yes. List the folder with listAll() (client) or bucket.getFiles({ prefix }) (server), collect a URL per file, and pass the list to createZip(). There is no folder-download button in the Firebase console or client SDK.

Does Firebase have a built-in ZIP export?

No. Cloud Storage for Firebase stores and serves individual objects; zipping is left to your application, a Cloud Function, or a service like Eazip.

Do I need a backend to zip Firebase Storage files?

Not if your Security Rules already allow the signed-in user to read the folder — listAll() and getDownloadURL() from the Web SDK are enough. Add a server step only for private files or centralized authorization.

Why do some Firebase Storage downloads fail with a CORS error?

Standard firebasestorage.googleapis.com download URLs already allow browser GETs. A CORS failure usually means you fetched a custom-domain or direct storage.googleapis.com URL that needs its own CORS configuration via gcloud storage buckets update --cors-file.

How many files can I zip from Firebase Storage in the browser?

There is no hard limit, but tab memory, listing size, and signed URL lifetime all shrink as the folder grows. Move to Eazip Cloud once a folder runs into the thousands of files or multiple gigabytes.

Continue with When to use Eazip Cloud, Input types, and Create a ZIP from remote URLs.