首页 > 解决方案 > 下载多个图像后超出 Cloud Storage for Firebase 带宽配额 - 最佳做法是什么?

问题描述

我正在构建一个 iOS 应用程序,其数据存储在 Firestore 中,相关图像存储在 Cloud Storage for Firebase 中。从本质上讲,我的应用程序的起始屏幕是一个滚动的卡片列表,这些卡片代表来自我的 Firestore 集合之一的文档和关联的图像(从 Cloud Storage 中提取,使用文档标题匹配)。

为了生成起始滚动视图数据,每次打开我的应用程序时,我都会调用 Firestore 和 Cloud Storage 来填充我的本地结构并检索图像(其中大约 10 个,每个 600 像素 x 400 像素,大小在 300-500 KB 之间)。

我目前正在使用免费的 Spark 计划。我的 Firestore 配额很好,但昨天,我在模拟器中测试了该应用程序(可能运行了大约 60 次?)并且超过了 Cloud Storage 调用的 1 GB 带宽限制。我认为这是因为我正在下载大量图像而不是将它们存储在本地(因为每次运行应用程序时我都会再次下载它们?)。

以下是每次打开应用程序以获取所有数据和相关图像时运行的代码:

//  StoryRepository.swift

import Foundation
import FirebaseFirestore
import FirebaseStorage
import FirebaseFirestoreSwift

class StoryRepository: ObservableObject { // listen to any updates
    let db = Firestore.firestore()
    let storage = Storage.storage()
    
    @Published var stories = [Story]() // Story is a local struct with vars for title, previewImage (the associated card image I get from Cloud Storage), and other data in Firestore. 
    
    init() {
        loadStoryCardData()
    }
    
    func loadStoryCardData() {
        db.collection("stories").addSnapshotListener{ (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("Error fetching documents: \(error!)")
                return
            }
            
            // create Cloud Storage reference
            let storageRef = self.storage.reference()
            
            // each document represents a story. get the title of that story, and then fetch the image from Cloud Storage that has the same filename as that title.
            documents.forEach { document in
                guard let title = document["title"] as? String else {
                    print("Could not read story title.")
                    return
                }
                
                let primaryImageRef = storageRef.child("storyCardPrimaryImages/" + title + ".jpg")

                // Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
                primaryImageRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
                    if let error = error {
                        print("Error fetching primary image: \(error)")
                        return
                    } else {
                        if let image = UIImage(data: data!) {
                            self.stories.append(Story(title: title, previewImage: image, data: document.data())!)
                        }
                    }
                }
            }
        }
    }
}

我只是想知道如何优化这个,因为当我发布这个应用程序并获得用户时,我可以想象我的带宽会去哪里。我是否应该将本地结构和图像存储在 iOS FileManager 中,以便在应用程序首次运行时只下载一次?如果 Firestore 或 Cloud Storage 中的任何内容发生变化,我将如何更新本地数据?

我曾考虑以较小的尺寸存储图像,但我真的需要它们在我的应用程序中为 600 像素 x 400 像素。如果可能的话,我更愿意继续使用免费的 Spark 计划。老实说,我只是有点吃惊,因为我在测试时已经遇到了配额限制——当只有我在运行应用程序时。总的来说,我有点不知所措——任何建议都会非常非常感激。

标签: iosswiftfirebasegoogle-cloud-firestorefirebase-storage

解决方案


我是否应该将本地结构和图像存储在 iOS FileManager 中,以便在应用程序首次运行时只下载一次?

使用这样的本地缓存绝对是减少总带宽使用的一种好方法。

如果 Firestore 或 Cloud Storage 中的任何内容发生变化,我将如何更新本地数据?

那将由你来设计。通常,执行此操作的一种方法是让您的进程更新存储中的对象,同时更新有关图像的一些元数据,并将其存储在 Firestore 中。您的应用可以查询 Firestore 以获取更改,然后在再次下载之前检查您本地缓存的文件是否是最新的。

我曾考虑以较小的尺寸存储图像,但我真的需要它们在我的应用程序中为 600 像素 x 400 像素。

您可以随时增加 JPG 压缩量,这也会降低图像质量。这是一个权衡,您必须根据自己的喜好进行试验。


推荐阅读