我想将图像存储在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 -- ✅")
})
})
}
}
答案 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) }
})
}
})