在 iOS 终止任务之前,如何让非常大的文件有时间上传到 firebase?

Posted

技术标签:

【中文标题】在 iOS 终止任务之前,如何让非常大的文件有时间上传到 firebase?【英文标题】:How do you allow very large files to have time to upload to firebase before iOS terminates the task? 【发布时间】:2022-01-10 06:44:27 【问题描述】:

我有一个视频共享应用,当您将视频保存到 Firebase 存储时,它非常适合大约 1 分钟或更短的视频。

我遇到的问题是,当我尝试发布更长的视频(1 分钟或更长)时,它永远不会保存到 firebase。

我唯一能想到的就是我得到的这个错误,而且这个错误只在我点击保存按钮后大约 30 秒出现:

[BackgroundTask] 后台任务 101(“GTMSessionFetcher-firebasestorage.googleapis.com”)创建于 30 多秒前。在后台运行的应用程序中,这会产生终止风险。请记住及时为您的任务调用 UIApplication.endBackgroundTask(_:) 以避免这种情况。

这是我将视频保存到 firebase 的代码。

func saveMovie(path: String, file: String, url: URL) 
    var backgroundTaskID: UIBackgroundTaskIdentifier?
    // Perform the task on a background queue.
    DispatchQueue.global().async 
        // Request the task asseration and save the ID
        backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish doing this task", expirationHandler: 
            // End the task if time expires
            UIApplication.shared.endBackgroundTask(backgroundTaskID!)
            backgroundTaskID = UIBackgroundTaskIdentifier.invalid
        )
        // Send the data synchronously
        do 
            let movieData = try Data(contentsOf: url)
            self.storage.child(path).child("\(file).m4v").putData(movieData)
         catch let error 
            fatalError("Error saving movie in saveMovie func. \(error.localizedDescription)")
        
        //End the task assertion
        UIApplication.shared.endBackgroundTask(backgroundTaskID!)
        backgroundTaskID = UIBackgroundTaskIdentifier.invalid
    

关于如何让我的视频有时间上传有什么建议吗?

【问题讨论】:

我看不出您的代码中如何涉及 Firebase 存储。 @ElTomato "firebasestorage.googleapis.com" 和 "storage.child(path).child("\(file).m4v").putData(movieData)" 都指向 Firebase 存储。 @FrankvanPuffelen 好的,谢谢。但是一个叫“storage”的家伙是从哪里来的呢? @ElTomato 抱歉,我的函数有点令人困惑,因为我是新手。但是存储只是顶部的一个变量,等于Storage.storage().reference() 为什么要这样做DispatchQueue.global().async,因为 Firebase 函数是异步的。但是你有这个// Send the data synchronously 但同样,Firebase 函数是异步的。最后一个问题:既然你知道文件路径,为什么可以直接用.putFileUpload The File 转换为Data?哦 - 对于您的 UI,如果需要,您可以 Monitor Progress 获取进度条 【参考方案1】:

好久不见……

您所要做的就是使用.putFile("FileURL") 而不是.putdata("Data")。 Firebase 文档说在上传大文件时应该使用putFile() 而不是putData()

但困难的部分是由于某种原因,您无法直接上传从 didFinishPickingMediaWithInfo 函数获得的电影 URL,firebase 只会给您一个错误。所以我所做的是获取电影的数据,将电影数据保存到文件管理器中的路径,然后使用文件管理器路径 URL 直接上传到对我有用的 firebase。

            //Save movie to Firestore
        do 
            // Convert movie to Data.
            let movieData = try Data(contentsOf: movie)
            // Get path so we can save movieData into fileManager and upload to firebase because movie URL does not work, but fileManager url does work.
            guard let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent(postId!) else  print("Error saving to file manager in addPost func"); return 
            do 
                try movieData.write(to: path)
                // Save the file manager url file to firebase storage
                Storage.storage().reference().child("Videos").child("\(postId!).m4v").putFile(from: path, metadata: nil)  metadata, error in
                    if let error = error 
                        print("There was an error \(error.localizedDescription)")
                     else 
                        print("Video successfully uploaded.")
                    
                    // Delete video from filemanager because it would take up too much space to save all videos to file manager.
                    do 
                        try FileManager.default.removeItem(atPath: path.path)
                     catch let error 
                        print("Error deleting from file manager in addPost func \(error.localizedDescription)")
                    
                
             catch let error 
                print("Error writing movieData to firebase \(error.localizedDescription)")
            
         catch let error 
            print("There was an error adding video in addPost func \(error.localizedDescription)")
        

【讨论】:

以上是关于在 iOS 终止任务之前,如何让非常大的文件有时间上传到 firebase?的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin iOS 后台应用程序终止

应用程序在 onStop() 完成之前终止

为啥 Windows 任务管理器在写入非常大的文件时显示内存增加?我应该担心吗? [关闭]

如何终止 BufferedInputStream .read() 调用

ios 8 如何让整个应用伸展到更大的屏幕而不是自动布局

如何在python中解析非常大的文件?