Firebase Storage — to chmurowa usługa przechowywania plików użytkowników, wchodząca w skład ekosystemu Firebase od Google, przeznaczona do przesyłania i pobierania obrazów, wideo, audio i innych danych binarnych z aplikacji mobilnych i internetowych. W przeciwieństwie do zwykłego dysku w chmurze, Storage integruje się z Firebase Authentication i Security Rules, co pozwala elastycznie rozgraniczać dostęp do każdego pliku na poziomie żądania. Według danych Google Firebase (2026), usługa przetwarza ponad 500 milionów operacji na plikach dziennie, zapewniając skalowalne przechowywanie bez konieczności zarządzania infrastrukturą serwerową.
Najważniejsze
Firebase Storage — to chmurowe przechowywanie obiektów, zbudowane na bazie Google Cloud Storage, które udostępnia SDK dla platform Android, iOS i internetowych. Każdy plik przechowywany jest jako obiekt w zasobniku Google Cloud i adresowany ścieżką przypominającą system plików: gs://bucket-name/path/to/file.jpg. Rozmiar pojedynczego pliku może osiągnąć 5 TB, co pozwala przechowywać dowolne dane multimedialne bez wstępnej kompresji.
Architektura Firebase Storage wykorzystuje model referencyjny linków (gsutil references), a nie klasyczną hierarchię folderów, chociaż SDK udostępnia interfejs z katalogami dla wygody programisty. Fizycznie wszystkie obiekty przechowywane są w płaskiej przestrzeni nazw zasobnika, a wirtualne foldery tworzone są za pomocą prefiksów ścieżki. Zapewnia to liniową wydajność wyszukiwania niezależnie od liczby plików.
Kluczową zaletą Firebase Storage w porównaniu do bezpośredniego użycia Google Cloud Storage jest wbudowana integracja z Firebase Authentication i Security Rules. Programista nie musi konfigurować osobnych ról IAM i kont serwisowych: reguły dostępu pisane są w języku deklaratywnym, podobnym do Firebase Realtime Database Rules, i stosowane automatycznie przy każdym zapytaniu.
Zasobnik Firebase Storage tworzony jest automatycznie po podłączeniu usługi w konsoli Firebase. Ścieżka do pliku budowana jest według zasady /nazwa_folderu/nazwa_pliku i może zawierać zagnieżdżone poziomy. Zaleca się organizowanie ścieżek według schematu /users/{userId}/images/{imageId}.jpg dla izolacji danych między użytkownikami. Taka struktura upraszcza pisanie reguł bezpieczeństwa, ponieważ ścieżka zawiera identyfikator właściciela.
Ważne jest, aby zrozumieć, że Firebase Storage nie jest relacyjną bazą danych ani serwerem plików w klasycznym rozumieniu. To przechowywanie obiektów, zoptymalizowane do operacji odczytu i zapisu całych plików. Aktualizacja części pliku jest niemożliwa: przy ponownym przesłaniu pod tą samą ścieżką stary obiekt jest zastępowany nowym. Do przechowywania małych strukturyzowanych danych użyj Firebase Realtime Database lub Cloud Firestore.
Cennik Firebase Storage zależy od objętości przechowywanych danych i liczby operacji. Darmowy limit (Spark) obejmuje 5 GB przestrzeni, 20 000 operacji zapisu i 50 000 operacji odczytu dziennie. Płatny limit (Blaze) rozliczany jest według rzeczywistego użycia: $0,026 za GB przechowywanych danych, $0,05 za 10 000 operacji zapisu i $0,004 za 10 000 operacji odczytu. Dodatkowo pobierana jest opłata za ruch wychodzący.
Dla większości aplikacji mobilnych z kilkoma tysiącami użytkowników darmowy limit wystarcza na etapie prototypowania i testowania. Przy skalowaniu do setek tysięcy użytkowników koszty Storage rzadko przekraczają $50–$100 miesięcznie przy zoptymalizowanym podejściu do przesyłania i buforowaniu po stronie klienta.
Przesyłanie pliku do Firebase Storage odbywa się za pośrednictwem odpowiedniej metody SDK, która przyjmuje ścieżkę w przechowywaniu i dane pliku (tablicę bajtów, URI, strumień lub Bitmap). SDK automatycznie zarządza połączeniem, segmentuje plik na części przy dużym rozmiarze i udostępnia wywołania zwrotne do śledzenia postępu. Przesyłanie odbywa się bezpośrednio z urządzenia klienckiego do Google Cloud, z pominięciem twojego serwera, co zmniejsza obciążenie własnej infrastruktury.
Dla Android Firebase Storage SDK używa klas StorageReference i UploadTask. StorageReference tworzona jest z ścieżki głównej przez Firebase.storage.reference i wskazuje na konkretny plik w zasobniku. UploadTask zwraca nasłuchiwacze postępu, wstrzymania i zakończenia. W przypadku przerwania połączenia UploadTask automatycznie wznawia przesyłanie od ostatniego pomyślnie przesłanego bajtu — to zachowanie nazywa się dokańczaniem (resumable upload).
Metadane pliku (Content-Type, pola niestandardowe) przekazywane są jako osobny obiekt SettableMetadata przy rozpoczęciu przesyłania. Prawidłowe ustawienie Content-Type jest krytyczne dla poprawnego wyświetlania plików w przeglądarce i działania buforowania CDN. Firebase Storage obsługuje wszystkie standardowe typy MIME: image/jpeg, image/png, video/mp4, application/pdf i inne.
Metadane pliku zawierają pola systemowe (Content-Type, Cache-Control, Content-Disposition) i niestandardowe pary klucz-wartość (customMetadata). Pola systemowe kontrolują nagłówki HTTP podczas pobierania. Na przykład Cache-Control: public, max-age=31536000 włącza buforowanie odpowiedzi na rok, co znacznie zmniejsza liczbę ponownych pobrań tego samego pliku i oszczędza przepustowość.
Niestandardowe metadane są wygodne do przekazywania dodatkowych informacji o pliku bez tworzenia osobnej kolekcji w Firestore. Na przykład w polu uploadedBy można zapisać userId użytkownika, który przesłał plik, co upraszcza implementację galerii z treścią autorską. Niestandardowe metadane nie są osobno chronione przez Security Rules — dostęp do nich regulują te same reguły, co do samego pliku.
W przypadku konieczności przesłania wielu plików jednocześnie (na przykład zdjęć z galerii) nie zaleca się uruchamiania niezależnych UploadTask równolegle bez ograniczeń. Na urządzeniach mobilnych równoległe przesyłanie więcej niż 3–5 plików prowadzi do przeciążenia stosu sieciowego i przekroczenia czasu. Optymalną strategią jest użycie limitu współbieżności 3 lub sekwencyjne przesyłanie z wyświetlaniem ogólnego paska postępu.
Do przetwarzania serwerowego po przesłaniu (generowanie miniaturek, kompresja, moderacja treści) użyj wyzwalacza Firebase Cloud Functions: functions.storage.object().onFinalize(). Ta funkcja jest wywoływana automatycznie po zakończeniu przesyłania każdego pliku i może zapisać przetworzoną kopię pod inną ścieżką. Więcej na ten temat w sekcji o typowych scenariuszach.
Firebase Storage obsługuje dwa sposoby pobierania: bezpośrednie pobieranie przez SDK z otrzymaniem tablicy bajtów lub lokalnego pliku oraz uzyskanie bezpośredniego download URL do dostępu przez HTTP. Bezpośredni URL można użyć do wyświetlania obrazów w ImageView, w WebView lub do udostępnienia linku użytkownikowi. Download URL generowany jest z tokenem bezpieczeństwa, który można unieważnić w konsoli Firebase.
Metoda storageReference.downloadUrl zwraca URL w formacie https://firebasestorage.googleapis.com/v0/b/{bucket}/o/{path}?alt=media&token={token}. Token bezpieczeństwa jest automatycznie dołączany do URL przy generowaniu, więc link można przekazywać osobom trzecim (na przykład w komunikatorze) bez ryzyka nieautoryzowanego dostępu. Jednak jeśli token został skompromitowany, można go unieważnić przez konsolę Firebase w sekcji Storage — po tym wszystkie linki z tym tokenem przestaną działać.
Do buforowania pobranych plików po stronie klienta użyj lokalnego przechowywania i mechanizmu ETag lub MD5-hash. Firebase Storage zwraca nagłówek HTTP ETag przy zapytaniu o plik, który można porównać z lokalnie zapisaną wartością i uniknąć ponownego pobierania niezmienionych plików. Jest to szczególnie przydatne dla treści multimedialnych: awatarów, okładek, podglądów — plików, które są rzadko aktualizowane, ale często żądane.
Download URL z tokenem to główny sposób udostępniania dostępu do plików dla nieuwierzytelnionych użytkowników (na przykład do wyświetlania obrazu w kanale aktualności). Token generowany jest raz i nie zmienia się do momentu unieważnienia, więc URL można zapisać w bazie danych (na przykład obok pola avatarUrl w Firestore). Przy zmianie awatara stary plik jest usuwany, a nowy URL generowany i zapisywany.
Ważne jest, aby pamiętać: posiadanie download URL nie anuluje Security Rules. Jeśli reguła zabrania odczytu pliku, metoda downloadUrl zwróci błąd Permission Denied. Oznacza to, że nawet znając poprawną ścieżkę do pliku, nieuwierzytelniony klient nie będzie mógł uzyskać linku. Po uzyskaniu URL dostęp do pliku odbywa się przez HTTP, z pominięciem Security Rules — dlatego token jest jedyną ochroną download linku.
HTTP ETag — to identyfikator wersji pliku, który zmienia się przy każdej modyfikacji zawartości. Firebase Storage automatycznie zwraca ETag w odpowiedzi na zapytanie GET. Aplikacja kliencka może zapisać ETag w lokalnym buforze i przy ponownym zapytaniu wysłać nagłówek If-None-Match: {etag}. Jeśli plik się nie zmienił, serwer zwróci status 304 Not Modified bez przesyłania danych.
Do implementacji inteligentnego buforowania w aplikacji mobilnej użyj kombinacji lokalnego systemu plików i bazy danych (na przykład Room do przechowywania par ścieżka-ETag). Podczas pobierania pliku sprawdź ETag z bazy danych: jeśli zgadza się z serwerowym, użyj lokalnej kopii. Takie podejście zmniejsza przepustowość o 60–80% dla statycznych plików multimedialnych i przyspiesza ładowanie ekranów z galeriami.
Security Rules — to deklaratywny język rozgraniczania dostępu do plików w Firebase Storage, wykonywany po stronie serwera Firebase. Każda reguła jest przypisana do ścieżki w zasobniku i określa warunki, przy których dozwolona jest operacja odczytu (read) lub zapisu (write). Reguły są sprawdzane przed każdym zapytaniem i nie mogą być ominięte przez kod kliencki. To jedyna linia ochrony danych przed nieautoryzowanym dostępem.
Podstawowa reguła — dostęp tylko dla uwierzytelnionych użytkowników: allow read, write: if request.auth != null. Taka reguła gwarantuje, że tylko zalogowani użytkownicy mogą odczytywać i zapisywać pliki. Do bardziej szczegółowej konfiguracji używana jest zmienna request.auth.uid, która zawiera identyfikator bieżącego użytkownika. Porównując uid z częścią ścieżki do pliku, można utworzyć izolowane przechowywanie dla każdego użytkownika.
Ważne: Security Rules nie są mechanizmem walidacji zawartości. Jeśli trzeba sprawdzić typ pliku, jego rozmiar lub obecność złośliwego kodu, użyj reguły request.resource, która zawiera metadane przesyłanego pliku. Dostępne są właściwości request.resource.size (rozmiar pliku), request.resource.contentType (typ MIME) i request.resource.md5Hash (suma kontrolna). Jednak pełna kontrola zawartości wykonywana jest po stronie serwera przez Cloud Functions.
| Scenariusz | Reguła Security Rules |
|---|---|
| Tylko uwierzytelnieni | allow read, write: if request.auth != null |
| Tylko właściciel | allow write: if request.auth.uid == userId |
| Publiczny odczyt | allow read: if true; allow write: if request.auth != null |
| Ograniczenie rozmiaru | allow write: if request.resource.size < 5 * 1024 * 1024 |
| Ograniczenie typu | allow write: if request.resource.contentType.startsWith('image/') |
Typowa konfiguracja dla aplikacji z awatarami użytkowników i galerią wygląda następująco. Użytkownik może zapisywać tylko w swoim katalogu /users/{userId}/, ale może odczytywać dowolny plik w tym katalogu (galeria publiczna). Rozmiar pliku jest ograniczony do 5 MB, a typ — tylko obrazy. Taka kombinacja reguł pokrywa 80% przypadków użycia Firebase Storage w aplikacjach społecznościowych i UGC.
Porada bezpieczeństwa: nigdy nie używaj reguły allow read, write: if true dla całego zasobnika. Otwiera to dostęp do zapisu każdemu, kto zna twój projectId. W 2025 roku nasiliły się ataki na niezabezpieczone zasobniki Firebase, gdy atakujący używali otwartego dostępu do przechowywania nielegalnych treści. Zawsze zaczynaj od minimalnie wymaganych uprawnień i rozszerzaj je tylko w przypadku wyraźnej potrzeby.
Cloud Functions wyzwalacz functions.storage.object().onFinalize() pozwala wykonać kontrolę zawartości po przesłaniu. Jeśli plik nie przejdzie walidacji (na przykład zawiera wirusa lub narusza zasady platformy), funkcja może go usunąć i powiadomić użytkownika. To jedyny sposób sprawdzenia rzeczywistej zawartości, ponieważ Security Rules widzą tylko metadane (rozmiar i typ MIME), a nie dane binarne.
Przykład walidacji: funkcja w Node.js pobiera przesłany plik do tymczasowego katalogu, przepuszcza go przez wykrywacz antywirusowy (na przykład ClamAV), a jeśli zagrożenie zostanie wykryte — usuwa plik i zapisuje zdarzenie w Firebase Crashlytics. Czas wykonania funkcji jest ograniczony do 540 sekund, co wystarcza do sprawdzenia plików o rozmiarze do 50 MB.
Rozważmy praktyczne przykłady integracji Firebase Storage w aplikacji Android w Kotlin. Kod używa standardowych klas Firebase SDK i demonstruje przesyłanie obrazu z galerii urządzenia, pobieranie pliku ze śledzeniem postępu oraz uzyskiwanie download URL. Wszystkie przykłady uwzględniają obsługę błędów i wstrzymywanie zadań w przypadku utraty połączenia.
Przed użyciem kodu upewnij się, że w pliku build.gradle dodano zależność implementation(platform("com.google.firebase:firebase-bom:33.0.0")) i implementation("com.google.firebase:firebase-storage"). Firebase BOM automatycznie dobiera kompatybilne wersje wszystkich SDK, co eliminuje konflikty wersji.
Pierwszy przykład — przesyłanie pliku wybranego przez użytkownika przez Intent ACTION_GET_CONTENT. Uri otrzymanego pliku przekazywany jest do Firebase Storage SDK, który samodzielnie odczytuje dane z tego Uri. Metoda putFile przyjmuje Uri i zwraca UploadTask — obiekt, przez który można śledzić postęp, wstrzymywać i wznawiać przesyłanie.
val storageRef = Firebase.storage.reference
val imageRef = storageRef.child(
"users/${auth.uid}/profile.jpg"
)
val metadata = SettableMetadata().apply {
contentType = "image/jpeg"
customMetadata = mapOf(
"uploadedBy" to auth.uid!!
)
}
imageRef.putFile(imageUri, metadata)
.addOnSuccessListener {
Log.d("Storage", "Plik przesłany")
}
.addOnFailureListener { e ->
Log.e("Storage", "Błąd: ${e.message}")
}
W powyższym przykładzie zmienna storageRef to główne odniesienie do zasobnika projektu. Metoda child przyjmuje łańcuch ścieżki i zwraca StorageReference wskazującą na konkretny plik. Jeśli plik pod wskazaną ścieżką już istnieje, zostanie nadpisany. Metadane contentType i customMetadata przekazywane są przez obiekt SettableMetadata, który jest dołączany do zapytania putFile.
Drugi przykład demonstruje pobieranie pliku z otrzymaniem tablicy bajtów do wyświetlenia w ImageView. Metoda getBytes(<maxSize>) pobiera cały plik do pamięci. Dla plików większych niż 10 MB użyj getFile(<localUri>) — zapisuje on zawartość bezpośrednio do lokalnego pliku bez przechowywania w pamięci RAM, co zapobiega OutOfMemoryError.
val islandRef = storageRef.child("images/island.jpg")
val ONE_MEGABYTE: Long = 1024 * 1024
islandRef.getBytes(ONE_MEGABYTE)
.addOnSuccessListener { bytes ->
imageView.setImageBitmap(
BitmapFactory.decodeByteArray(
bytes, 0, bytes.size
)
)
}
.addOnFailureListener { e ->
Log.e("Storage", "Nie udało się przesłać: ${e.message}")
}
Do uzyskania download URL (na przykład, aby zapisać link w Firestore) służy metoda downloadUrl:
islandRef.downloadUrl.addOnSuccessListener { uri ->
Log.d("Storage", "Download URL: $uri")
// Zapisz uri.toString() w Firestore
}
Porada: downloadUrl generowany jest raz i jest stabilny, dopóki nie zostanie unieważniony. Zapisz go w bazie danych przy pierwszym przesłaniu, a nie żądaj go za każdym razem przy wyświetlaniu pliku. Zmniejsza to liczbę zapytań do Firebase Storage i przyspiesza działanie interfejsu.
Firebase Storage jest używany w aplikacjach mobilnych do przechowywania wszelkich plików użytkowników i systemowych. Najczęstsze scenariusze to awatary i zdjęcia profilowe, obrazy w kanale treści, pliki wideo i audio, dokumenty (PDF, DOCX) do wymiany między użytkownikami, a także kopie zapasowe niewielkiej ilości danych. We wszystkich tych przypadkach Storage pełni rolę specjalistycznego przechowywania plików w połączeniu z Firestore do przechowywania metadanych i linków.
Aplikacje społecznościowe — najczęstszy przypadek użycia. Każdy użytkownik przesyła awatar, zdjęcia postów i pliki multimedialne. Struktura ścieżek /users/{uid}/posts/{postId}/image.jpg pozwala izolować dane i upraszcza Security Rules. Przy usunięciu użytkownika Cloud Function może przejść przez wszystkie katalogi użytkownika i wyczyścić przechowywanie. Według bloga Firebase (2025), taki wzorzec jest używany w 70% projektów produkcyjnych na Firebase.
Aplikacje e-commerce używają Firebase Storage do przechowywania zdjęć produktów, katalogów i plików PDF z instrukcjami. W tym przypadku dostęp do plików jest zwykle publiczny (odczyt bez autentykacji), a zapis — tylko dla administratorów przez Cloud Functions z kontrolą uprawnień. Download URL produktów zapisywany jest w Firestore obok pozostałych danych produktu, co pozwala wyświetlać obrazy bez dodatkowych zapytań do Storage.
Komunikatory i czaty przechowują w Firebase Storage obrazy i wiadomości głosowe wysyłane w dialogach. Ścieżka budowana jest jako /chats/{chatId}/messages/{messageId}.jpg. Dostęp do odczytu — tylko dla uczestników czatu, co jest sprawdzane przez Security Rules z użyciem danych z Firestore. To jeden z nielicznych scenariuszy, gdzie reguła odczytuje dane z innej usługi Firebase: allow read: if firestore.exists(/databases/(default)/documents/chats/{chatId}/members/{request.auth.uid}).
Najczęściej zadawane pytania
Firebase Storage — to nadbudowa nad Google Cloud Storage z integracją Firebase Authentication i Security Rules. Programista nie musi konfigurować ról IAM i kont serwisowych. Google Cloud Storage oferuje szersze możliwości (powiadomienia Pub/Sub, Object Lifecycle Management), ale wymaga ręcznego zarządzania dostępem przez GCP IAM.
Ograniczenie rozmiaru ustawia się w Security Rules przez request.resource.size. Przykład: allow write: if request.resource.size <= 5 * 1024 * 1024 ogranicza pliki do 5 MB. Dodatkowo można sprawdzić po stronie klienta przed wysłaniem, aby nie marnować przepustowości użytkownika przy ewidentnie niedozwolonym pliku.
Tak, do usunięcia służy metoda delete() obiektu StorageReference: storageRef.child("path").delete(). Operacja usunięcia jest nieodwracalna i usuwa plik z zasobnika natychmiast. Usunąć plik można tylko wtedy, gdy Security Rules zezwalają na write dla tej ścieżki. Po usunięciu download URL przestaje działać.
W Security Rules zezwól na read dla wszystkich (lub uwierzytelnionych) i zabroń write: allow read: if request.auth != null; allow write: if false. Zapis w tym trybie jest możliwy tylko przez konto serwisowe Firebase Admin SDK — na przykład z Cloud Functions z uprawnieniami administracyjnymi. To standardowy wzorzec dla katalogów produktów i treści publicznych.
UploadTask używa protokołu resumable upload opartego na HTTP PUT z segmentacją. W przypadku przerwania przesyłanie wznawiane jest od ostatniego potwierdzonego bajtu, a nie rozpoczynane od nowa. Do włączenia tego zachowania nie są wymagane dodatkowe ustawienia — SDK robi to automatycznie przy rozmiarze pliku powyżej 1 MB.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również