简体   繁体   English

iOS Swift:Firebase 存储上传错误 - 只有初始文件上传有效

[英]iOS Swift: Firebase Storage upload error - only the initial file upload works

Environment: Xcode 12.0.1 (Swift 5.x) iOS 13 Firebase 6.34.0 FirebaseFirestore 1.19.0 FirebaseStorage 3.9.1 GoogleDataTransport 7.5.1 PromisesObjC 1.2.11环境:Xcode 12.0.1 (Swift 5.x) iOS 13 Firebase 6.34.0 FirebaseFirestore 1.19.0 FirebaseStorage 3.9.1 GoogleDataTransport 7.5.1 PromisesObjC 1.2.11

Problem: I initialize Firebase in iOS app and successfully write database data to Cloud FireStore.问题:我在 iOS 应用程序中初始化 Firebase 并成功将数据库数据写入 Cloud FireStore。 I then upload related video file to Firebase Storage with an asynch call.然后我通过异步调用将相关视频文件上传到 Firebase 存储。

  1. Cloud Firestore database writes ALWAYS work. Cloud Firestore 数据库写入始终有效。
  2. Using the index generated from Cloud Firestore write, Firebase storage is then used to upload a video and a data file with names as the index from (1) above.使用从 Cloud Firestore 写入生成的索引,然后使用 Firebase 存储上传视频和数据文件,名称为上述 (1) 中的索引。

The first first file upload always works with a new app launch.第一个文件上传始终适用于新的应用程序启动。 The second or any additional file upload fails with the following error:第二次或任何其他文件上传失败,并显示以下错误:

cloud storage VIDEO file upload error: Error Domain=FIRStorageErrorDomain Code=-13000 "An unknown error occurred, please check the server response."云存储视频文件上传错误:Error Domain=FIRStorageErrorDomain Code=-13000“发生未知错误,请检查服务器响应。” UserInfo={object=PBY7Ost7nPWD8jWWF4qG.mov, ResponseBody=Can not finalize upload. UserInfo={object=PBY7Ost7nPWD8jWWF4qG.mov, ResponseBody=无法完成上传。 Current size is 1692167. Expected final size is 1665242 ., bucket=launch-me-47860.appspot.com, data={length = 83, bytes = 0x43616e20 6e6f7420 66696e61 6c697a65 ... 31363635 3234322e }, data_content_type=text/plain;当前大小为 1692167。预期最终大小为 1665242 .,bucket=launch-me-47860.appspot.com, data={length = 83, bytes = 0x43616e20 6e6f7420 66696e61 6c696e61 6c637a3623e, 3_3623e 6c635a3636e, 3 _ 3 6 3 3 6 3 6 3 6 3 6 3 6 3 6 3 5 charset=utf-8, NSLocalizedDescription=An unknown error occurred, please check the server response., ResponseErrorDomain=com.google.HTTPStatus, ResponseErrorCode=400} charset=utf-8, NSLocalizedDescription=发生未知错误,请检查服务器响应。, ResponseErrorDomain=com.google.HTTPStatus, ResponseErrorCode=400}

I have found similar questions posted from 2016 and 2017 but this Firebase write problem seems different as the initial upload always works and then the next time I try to perform an upload it fails with the error.我发现了 2016 年和 2017 年发布的类似问题,但这个 Firebase 写入问题似乎有所不同,因为初始上传始终有效,然后下次我尝试执行上传时,它因错误而失败。

I added a routine to try additional upload attempts if the first upload fails.如果第一次上传失败,我添加了一个例程来尝试额外的上传尝试。 They all fail.他们都失败了。 Here is the upload code:下面是上传代码:

    // MARK: Write file to Firebase Cloud Storage
    private func fbCloudFileWrite(indexName: String) {
        let fbStorage = Storage.storage()
        print("(DEBUG FB) fbCloudFileWrite: upload indexName.csv and indexName.mov")
        // now upload file to cloud FireStore
        let fbStorageRef = fbStorage.reference()
        // Create a reference to the file you want to upload
        //let LaunchMeDataRef = fbStorageRef.child("LaunchMe/" + indexName + ".csv")
        //let LaunchMeVideoRef = fbStorageRef.child("LaunchMe/" + indexName + ".mov")
        var LaunchMeDataRef = fbStorageRef.child(indexName + ".csv")
        var LaunchMeVideoRef = fbStorageRef.child(indexName + ".mov")
        // Upload the file to the path "images/rivers.jpg"
        fbWriteAttempts += 1
        DispatchQueue.main.async {
            print("(DEBUG FB) ***** write attemp #: \(self.fbWriteAttempts)")
            if let vURL = self.videoURL, let dURL = self.dataFileURL {
                let uploadVideoTask = LaunchMeVideoRef.putFile(from: vURL, metadata: nil) { metadata, err in
                    if let err = err {
                        print("(DEBUG FB) cloud storage VIDEO file upload error: \(err)")
                        if self.fbWriteAttempts < 4 {
                            self.fbCloudFileWrite(indexName: indexName)
                        }
                    } else {
                        print("(DEBUG FB) video uploaded: \(indexName)")
                        let uploadDataTask = LaunchMeDataRef.putFile(from: dURL, metadata: nil) { metadata, err in
                            if let err = err {
                                print("(DEBUG FB) cloud storage SENSOR file upload error: \(err)")
                            } else {
                                print("(DEBUG FB) sensor data uploaded: \(indexName)")
                                print("(DEBUG FB) set newRecording = false to prevent duplicates")
                                // all files successfully uploaded. Set newRecording to false
                                self.newRecording = false
                            }
                        } // close uploadDataTask
                    } // close else
                } // close let uploadVideoTask
            } // close vURL unwrap
            else {
                print("(DEBUG FB) videoURL could not be unwrapped")
            }
        } // close Dispatch.main.async

Strangely enough, I was able to solve this problem by setting the URL variable of the movie local directory path within the VideoPlayerViewController instead of passing the URL in from the previous controller during the segue.奇怪的是,我能够通过在 VideoPlayerViewController 中设置电影本地目录路径的 URL 变量而不是在 segue 期间从前一个控制器传入 URL 来解决这个问题。 This makes no sense to me that this would be necessary except perhaps some caching that happens behind the scenes.这对我来说是没有意义的,除非可能在幕后发生一些缓存,否则这是必要的。

I know the correct URL is passed in as the correct video plays on the screen when it is passed in, yet the Firebase Storage upload tries to upload the previous video (hence the expected size error) when provided the same URL that played the correct video.我知道正确的 URL 是在传入正确的视频时在屏幕上播放时传入的,但是当提供与播放正确视频的 URL 相同的 URL 时,Firebase 存储上传会尝试上传上一个视频(因此出现预期的大小错误) .

New function added within the controller that sets the URL instead of passing it in (prior to performing the Firebase Storage upload):在控制器中添加的新函数用于设置 URL 而不是传入它(在执行 Firebase 存储上传之前):

private func setVideoStorageURL() {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let path = "output.mov"
        videoURL = paths[0].appendingPathComponent(path)
    }

whereas the previous implementation that was not working passed the URL into the controller:而先前不起作用的实现将 URL 传递给控制器​​:

if let destinationVC = segue.destination as? VideoPlayerViewController {
                print("(DEBUG) Setting data to be passed to VideoPlayerViewController")
                destinationVC.newRecording = newRecording
                //now set newRecording to false if it is true
                if newRecording {
                    newRecording = false
                }
                destinationVC.audioMode = audioMode
                destinationVC.selectedDevice = selectedDevice
                destinationVC.videoURL = passFileURL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM