从当前用户更新Firebase数据库

时间:2019-01-28 07:37:56

标签: swift firebase firebase-realtime-database firebase-storage

我想将图像存储在firebase存储中并创建url,而不是从firebase中的当前数据库中更新值,但是它不存储当前用户的firebase数据库中。这是我的代码,我在哪里做错了?

fileprivate func saveToFirebase(image: UIImage) {
    guard let imageData = image.jpegData(compressionQuality: 0.3) else { return }
    let uuidName = UUID().uuidString

    Storage.storage().reference().child("profile_images").child(uuidName).putData(imageData, metadata: nil) { (metadata, error) in
        if let err = error {
            print(" -- Failed to upload images -- ")
            print(" -- \(err) -- ")
            return
        }

        metadata?.storageReference?.downloadURL(completion: { (url, error) in
            if let err = error {
                print(" -- Failed to create URL -- ")
                print(" -- \(err) -- ")
                return
            }

            guard let profileImageURL = url?.absoluteString else { return }
            guard let currentUID = Auth.auth().currentUser?.uid else { return }
            let userProfileURL = ["profileImageURL": profileImageURL]

            Database.database().reference().child("users").child(currentUID).updateChildValues(userProfileURL, withCompletionBlock: { (error, reference) in
            if let err = error {
                    print(" -- Failed to create URL -- ")
                    print(" -- \(err) -- ")
                    return
                }
                print("✅ -- Successfully update user data -- ✅")
            })
        })
    }
}

2 个答案:

答案 0 :(得分:1)

首先,我们可以创建一个枚举来表示可能发生的不同故障。我们认为是错误的某些情况(例如后卫返回void或断开的可选链断裂)会静默失败。在这里,我们可封装不同故障情形需要被处理。

enum ProfileImageUploadError: Error {
    case unauthenticatedUser
    case invalidImageData
    case failedDataUpload(Error?)
    case failedDownloadURL(Error?)
    case failedProfileUpdate(Error?)

    var localizedDescription: String {
        switch self {
        case .failedDataUpload: return "Failed to upload data"
        case .failedDownloadURL: return "Failed to download URL"
        case .failedProfileUpdate: return "Failed to update profile"
        default: return "\(self)"
        }
    }

    var underlyingError: Error? {
        switch self {
        case .failedDataUpload(let err): return err
        case .failedDownloadURL(let err): return err
        case .failedProfileUpdate(let err): return err
        default: return nil
        }
    }
}

接下来,我们可以立即确定我们具有经过身份验证的用户,并且图像数据已签出。当防护失败时,我们调用完成块,传递该方案的错误情况。为了保持这种状态,我们构造了对存储和数据库提供程序的引用,并尝试了序列捕获错误。

鉴于最初上传数据没有错误,我们可以假设图像已上传。另外,除了使用可选的元数据,我们还可以使用我们之前构建的存储引用来下载URL。

随着我们继续通过操作的顺序,我们试图能够充分处理我们所认为的错误,直到成功完成时,此时我们可以返回保存到数据库火力地堡的URL。

func uploadProfileImage(_ image: UIImage, completion: @escaping (URL?, ProfileImageUploadError?) -> ()) {

    guard let currentUser = Auth.auth().currentUser else {
        return completion(nil, .unauthenticatedUser)
    }

    guard let imageData = image.jpegData(compressionQuality: 0.3) else {
        return completion(nil, .invalidImageData)
    }

    let storagePath = "profile_images/\(UUID().uuidString)"
    let databasePath = "users/\(currentUser.uid)/profileImageURL"

    let profileImageDataRef = Storage.storage().reference(withPath: storagePath)
    let profileImageURLRef = Database.database().reference(withPath: databasePath)

    profileImageDataRef.putData(imageData, metadata: nil) { (metadata, error) in
        guard error == nil else {
            return completion(nil, .failedDataUpload(error))
        }

        profileImageDataRef.downloadURL { (url, error) in
            guard let profileImageURL = url?.absoluteString else {
                return completion(nil, .failedDownloadURL(error))
            }

            profileImageURLRef.setValue(profileImageURL, withCompletionBlock: { (error, ref) in
                guard error == nil else {
                    return completion(nil, .failedProfileUpdate(error))
                }

                completion(url, nil)
            })
        }
    }
}

最后,这就是您在现有功能中使用该功能的方式。

fileprivate func saveToFirebase(image: UIImage) {
    uploadProfileImage(image) { (url, error) in
        if let error = error {
            print(" -- \(error.localizedDescription) -- ")
            print(" -- \(error.underlyingError.debugDescription) -- ")
        } else {
            print("✅ -- Successfully update user data -- ✅")
            print("✅ -- \(url.debugDescription) -- ✅")
        }
    }
}

这未经测试

所以要回顾一下,一些在你的函数中的行可以“失败”悄无声息,这可以通过充分处理“自选”和错误的完成或只是打印语句来解决。我认为这是导致URL下载导致问题的一系列可选属性,特别是metadata?.storageReference?.downloadURL中的元数据属性。

答案 1 :(得分:0)

尝试一下.. useruid是firbase uid

    let storageRef = Storage.storage().reference().child("profile_images").child(useruid)
                storageRef.putData(imagedata, metadata: nil, completion: { (metadatas, error) in
                    if error != nil {                                              
                     print("Couldn't Upload Image")
                                    } else {
                                        print("Uploaded")
                                      print(metadatas!)
                                        storageRef.downloadURL(completion: { (url, error) in
                                            if error != nil {
                                                print(error!)
                                                return

                                            }
                                            if url != nil {

                          let imageurl = String(describing: url!)
                         print(imageurl)                                            }
                                        })
                            }
                })