Интеграция Firebase Storage в мобильное приложение
Firebase Storage — объектное хранилище на базе Google Cloud Storage с Firebase Auth интеграцией. Правила доступа пишутся на том же языке, что и Firestore Rules, путь к файлу можно привязать к auth.uid. Для загрузки аватаров, документов, аудио и видео из мобильного приложения — стандартный выбор в Firebase-стеке.
Загрузка файла с progress
import storage from '@react-native-firebase/storage';
import { launchImageLibrary } from 'react-native-image-picker';
const uploadAvatar = async (userId: string) => {
const result = await launchImageLibrary({ mediaType: 'photo', quality: 0.8 });
if (result.didCancel || !result.assets?.[0]?.uri) return;
const localUri = result.assets[0].uri;
const ref = storage().ref(`avatars/${userId}.jpg`);
const task = ref.putFile(localUri);
task.on('state_changed',
snapshot => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
setUploadProgress(Math.round(progress));
},
error => {
console.error('Upload error:', error.code);
},
async () => {
const downloadURL = await ref.getDownloadURL();
await updateUserProfile({ photoURL: downloadURL });
}
);
};
putFile() принимает локальный путь (file://...), а не base64. На iOS launchImageLibrary возвращает ph:// URI — на некоторых версиях RN нужна конвертация в file:// через react-native-fs.
Правила безопасности Storage
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /avatars/{userId}.jpg {
allow read: if request.auth != null;
allow write: if request.auth.uid == userId
&& request.resource.size < 5 * 1024 * 1024 // 5 MB
&& request.resource.contentType.matches('image/.*');
}
match /documents/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId;
}
}
}
request.resource.size и request.resource.contentType — проверки на сервере, а не только клиентская валидация.
Resumable uploads для больших файлов
putFile() автоматически использует resumable upload для файлов >5 МБ. Для явного управления паузой/возобновлением:
const task = ref.putFile(localPath);
// Пауза при уходе в фон
AppState.addEventListener('change', state => {
if (state === 'background') task.pause();
if (state === 'active') task.resume();
});
Firebase Storage задача переживает перезапуск приложения только если сохранить task.snapshot.ref.fullPath и вызвать ref.putResumable() при следующем запуске. Без этого при крэше загрузка начнётся заново.
Оценка
Firebase Storage с загрузкой медиа, progress-индикатором и правилами доступа: 1–2 недели.







