- Published on
Firebase storage: ilovaga rasm va videolarni yuklash
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Nega Firestore emas, storage?
Firestore (biz shu paytgacha ishlatgan baza) matnli va oddiy ma'lumotlarni (ism, yosh, narx) saqlash uchun mo'ljallangan. Ammo rasm, video va audio kabi "og'ir" fayllarni to'g'ridan-to'g'ri Firestore'ga saqlab bo'lmaydi. Buning uchun Firebase alohida mahsulot yaratgan — Firebase Storage.
Storage — xuddi Google Drive yoki kompyuteringizdagi xotira kabi ishlaydi. Faylni Storage'ga yuklaymiz, Storage bizga URL manzilini beradi, va shu URL ni Firestore'ga matn sifatida saqlab qo'yamiz.
1. Storage'ni o'rnatish
- Firebase Console -> Storage bo'limiga o'ting va uni faollashtiring.
- Xcode'da
FirebaseStoragepaketini (package) qo'shing.
2. Rasmni saqlash (Eng yaxshi amaliyotlar bilan)
Rasmni shunchaki Storage root (asosiy papka) iga saqlash yomon g'oya. Millionlab foydalanuvchilar rasmlari bitta papkada yig'ilib qolsa, boshqarish qiyin bo'ladi. Eng yaxshi arxitektura: users -> {userId} -> {rasm_idsi}.jpg ko'rinishida saqlashdir.
import FirebaseStorage
import UIKit
class StorageManager {
static let shared = StorageManager()
private let storage = Storage.storage().reference()
// Foydalanuvchi profil rasmini saqlash
func saveProfileImage(userId: String, image: UIImage) async throws -> (path: String, url: String) {
// 1. Rasmni Data turiga (byte'larga) o'giring va siqing (compression)
guard let data = image.jpegData(compressionQuality: 0.8) else {
throw URLError(.badServerResponse)
}
// 2. Qayerga saqlashni ko'rsating (Fayl manzili)
let imageId = UUID().string
let userReference = storage.child("users").child(userId).child("\(imageId).jpeg")
// 3. Metadata (Bu JPEG rasm ekanini aytib qo'yish shart, aks holda xato ishlashi mumkin)
let meta = StorageMetadata()
meta.contentType = "image/jpeg"
// 4. Rasmni yuklaymiz
let _ = try await userReference.putDataAsync(data, metadata: meta)
// 5. Rasmni internetdan ko'rish mumkin bo'lgan Ochiq URL'ni olamiz
let downloadUrl = try await userReference.downloadURL()
return (userReference.fullPath, downloadUrl.absoluteString)
}
}
IMPORTANT
Rasmni siqmasdan (compression) yuklash juda xavfli! Bitta iPhone kamerasi orqali tushirilgan rasm 5-10 MB bo'ladi. Agar siz buni siqmasangiz, foydalanuvchilarning internet trafigi tugab qoladi va Storage xotirangiz tezda to'lib (puli tugab) qoladi. Har doim jpegData(compressionQuality: 0.2) kabi siqishdan foydalaning. Yoki Firebase'ning Resize Images extension'ini ulang (bu haqida keyinroq).
3. Rasm ma'lumotlarini Firestore'ga yozish
Rasmni Storage'ga yuklaganimizdan so'ng, qaytib kelgan path va URL ni Firestore'dagi User hujjatiga (User Profile) saqlab qo'yishimiz kerak.
func uploadProfileImage(image: UIImage) async {
do {
// 1. Rasmni Storage'ga yuklash
let result = try await StorageManager.shared.saveProfileImage(userId: "user123", image: image)
// 2. Path va URL ni Firestore dagi User ga saqlash
try await UserManager.shared.updateUserProfileImage(
userId: "user123",
path: result.path,
url: result.url
)
} catch {
print("Xatolik: \(error)")
}
}
Nega Path va URL ikkalasini ham saqlayapmiz?
- URL bizga ekranda rasmni ko'rsatish (
AsyncImage) uchun kerak. - Path bizga ertaga rasm kerak bo'lmay qolsa, Storage'dan rasmni aniq topib o'chirib tashlash (Delete) uchun kerak.
4. Rasmni Ekranda ko'rsatish (SwiftUI)
Firebase'dan rasm yuklab olish uchun o'zimiz kod yozishimiz ham mumkin edi, lekin SwiftUI da tayyor AsyncImage bor. U URL ni o'zi orqa fonda tez yuklab ekranga chizadi:
struct ProfileView: View {
let profileImageUrl: String? // Firestore dan kelgan url
var body: some View {
if let urlString = profileImageUrl, let url = URL(string: urlString) {
AsyncImage(url: url) { image in
image
.resizable()
.scaledToFill()
.frame(width: 150, height: 150)
.clipShape(Circle())
} placeholder: {
ProgressView() // Yuklanayotganda aylanib turuvchi loader
}
} else {
Image(systemName: "person.circle.fill") // Agar rasm yo'q bo'lsa (default)
.resizable()
.frame(width: 150, height: 150)
}
}
}
Rasmni o'chirish (Delete)
Foydalanuvchi o'z profil rasmini o'chirib tashlamoqchi bo'lsa:
- Firestore'dan avval saqlab qo'ygan
pathni olamiz. - StorageManager'ga yuboramiz:
func deleteImage(path: String) async throws {
let reference = storage.child(path)
try await reference.delete()
}
- O'chgandan so'ng, Firestore'dagi User hujjatidan
pathvaURLmaydonlarininil(yoki bo'sh) qilib yangilab qo'yamiz.