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

How do you allow very large files to have time to upload to firebase before iOS terminates the task?

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

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

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

[BackgroundTask] Background Task 101 ("GTMSessionFetcher-firebasestorage.googleapis.com"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.

这是我将视频保存到 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
    }
}

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

想了很久终于搞明白了...

您所要做的就是使用 .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)")
        }