iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Cloud Storage

Cloud Storage holds binary files (images, video, PDFs). The SDK signs upload requests so users go DIRECT to Google’s servers; rules gate who can read / write.

Upload, download, list, security

EXAMPLE
import { initializeApp } from 'firebase/app';
import {
    getStorage, ref, uploadBytes, uploadBytesResumable,
    getDownloadURL, deleteObject, listAll,
} from 'firebase/storage';

const storage = getStorage(initializeApp(firebaseConfig));

// 1) Simple upload
async function uploadAvatar(uid, file) {
    const r = ref(storage, \`avatars/${uid}/${file.name}\`);
    const result = await uploadBytes(r, file, {
        contentType: file.type,
        customMetadata: { uploadedBy: uid },
    });
    return getDownloadURL(result.ref);
}

// 2) Resumable upload with progress + pause
function uploadWithProgress(uid, file, onProgress) {
    const task = uploadBytesResumable(
        ref(storage, \`uploads/${uid}/${crypto.randomUUID()}\`),
        file,
    );
    task.on('state_changed',
        (snap) => {
            const pct = (snap.bytesTransferred / snap.totalBytes) * 100;
            onProgress(pct);
        },
        (err) => console.error(err),
        async () => {
            const url = await getDownloadURL(task.snapshot.ref);
            console.log('done', url);
        },
    );
    return task;   // task.pause() / task.resume() / task.cancel()
}

// 3) List + download URLs
async function listAvatars(uid) {
    const r = ref(storage, \`avatars/${uid}/\`);
    const { items, prefixes } = await listAll(r);
    return Promise.all(items.map(i => getDownloadURL(i)));
}

// 4) Delete
await deleteObject(ref(storage, \`avatars/${uid}/old.png\`));

// 5) Security rules — enforce size / type / ownership
rules_version = '2';
service firebase.storage {
    match /b/{bucket}/o {
        match /avatars/{uid}/{name=**} {
            allow read:  if true;                  // public read
            allow write: if request.auth != null &&
                request.auth.uid == uid &&
                request.resource.size < 5 * 1024 * 1024 &&
                request.resource.contentType.matches('image/.*');
        }
        match /private/{uid}/{name=**} {
            allow read, write: if request.auth != null && request.auth.uid == uid;
        }
    }
}

// 6) Process on upload — Cloud Function trigger
export const onAvatarUpload = onObjectFinalized(
    { region: 'us-east1' },
    async (event) => {
        if (!event.data.name.startsWith('avatars/')) return;
        // thumbnail it, scan for malware, etc.
    },
);

Why it matters

Always validate contentType + size in rules. Without them, anyone with auth uploads 10 GB malware files to your bucket and you pay the bandwidth + storage bills.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import { getStorage, ref, uploadBytes, getDownloadURL } from 'firebase/storage';
const storage = getStorage(app);
const r = ref(storage, 'avatars/' + uid + '.png');
await uploadBytes(r, file);
const url = await getDownloadURL(r);
Try it Yourself »

Discussion

Loading…