I just updated Firebase Storage to 5.0.0 and it looks like metadata.downloadURL() is not recognized anymore. (Value of type 'StorageMetadata' has no member 'downloadURL')
Though after looking in the documentation it should still be available :
https://firebase.google.com/docs/reference/swift/firebasestorage/api/reference/Classes/StorageMetadata#/c:objc(cs)FIRStorageMetadata(im)downloadURL
The project was cleaned & rebuilt already.
Am I missing something ?
Can you try Google Firebase docs
// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")
// Fetch the download URL
starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors
} else {
// Get the download URL for 'images/stars.jpg'
}
}
This is my version for Swift 3 / Swift 4.
Explanation of what happens in the code.
This is essentially the same answer as Sh_Khan's. But in his example the User already knows the bucket path. In my example, we get the path from an upload task. This was what has lead me to this question as well as what I think op was looking for as he was looking for metadata.downloadURL() replacement.
class StorageManagager {
private let storageReference: StorageReference
init() {
// first we create a reference to our storage
// replace the URL with your firebase URL
self.storageReference = Storage.storage().reference(forURL: "gs://MYAPP.appspot.com")
}
// MARK: - UPLOAD DATA
open func uploadData(_ data: Data, named filename: String, completion: #escaping (URL? , Error?) -> Void) {
let reference = self.storageReference.child(filename)
let metadata = StorageMetadata()
metadata.contentType = "ourType" // in my example this was "PDF"
// we create an upload task using our reference and upload the
// data using the metadata object
let uploadTask = reference.putData(data, metadata: metadata) { metadata, error in
// first we check if the error is nil
if let error = error {
completion(nil, error)
return
}
// then we check if the metadata and path exists
// if the error was nil, we expect the metadata and path to exist
// therefore if not, we return an error
guard let metadata = metadata, let path = metadata.path else {
completion(nil, NSError(domain: "core", code: 0, userInfo: [NSLocalizedDescriptionKey: "Unexpected error. Path is nil."]))
return
}
// now we get the download url using the path
// and the basic reference object (without child paths)
self.getDownloadURL(from: path, completion: completion)
}
// further we are able to use the uploadTask for example to
// to get the progress
}
// MARK: - GET DOWNLOAD URL
private func getDownloadURL(from path: String, completion: #escaping (URL?, Error?) -> Void) {
self.storageReference.child(path).downloadURL(completion: completion)
}
}
Let's try this code in Swift 4.2:
let imgData = UIImage.jpegData(self.imageView.image!)
let imageName = UUID().uuidString
let ref = Storage.storage().reference().child("pictures/\(imageName).jpg")
let meta = StorageMetadata()
meta.contentType = "image/jpeg"
self.uploadToCloud(data: imgData(0.5)!, ref: ref, meta: meta)
UploadToCloud Method:
` Method UploadToCloud
func uploadToCloud(data:Data, ref:StorageReference, meta:StorageMetadata) {
ref.putData(data, metadata: meta) { (metaData, error) in
if let e = error {
print("==> error: \(e.localizedDescription)")
}
else
{
ref.downloadURL(completion: { (url, error) in
print("Image URL: \((url?.absoluteString)!)")
})
}
}
}
This question pops up for all language searches. Hence for Kotlin, the solution is something of the kind below:
val photoRef = FirebaseStorage.getInstance()
.reference.child("images/stars.jpg")
// Code ommited - Do some saving - putFile
photoRef.downloadUrl.addOnSuccessListener({ uri ->
product.imageUrl = uri.toString()
})
However, this is not a good solution. You are better off saving the path and then re-constructing the full Url on demand. For example:
photoRef.downloadUrl.addOnSuccessListener({ uri ->
val imagePath = uri.toString()
// Save to database
})
Now, you can use it later, and only on demand:
FirebaseStorage.getInstance().reference.child(product.imageUrl).downloadUrl
.addOnSuccessListener { uri ->
String imageUrl = uri.toString()
// Load in images
}
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
if error != nil {
print(error as Any)
return
}
guard let uid = user?.user.uid else {
return
}
self.dismiss(animated: true, completion: nil)
//Добавляем картинку в firebase. Надо добавить в Pods file pod 'Firebase/Storage' и запустить терминал
let imageName = NSUUID().uuidString
let storageRef = Storage.storage().reference()
// Create a reference to the file you want to download
let starsRef = storageRef.child("profile_images").child("\(imageName).png")
let uploadData = self.profileImageView.image?.pngData()
starsRef.putData(uploadData!, metadata: nil, completion: { (metadata, error) in
if error != nil {
print(error as Any)
}
if let profileImageUrl = metadata?.path {
let values = ["name": name, "email": email, "profileImage": profileImageUrl]
self.registerUserIntoDatabaseWithUID(uid: uid, values: values)
}
})
}
If you are stuck in converting URL to string... you can try this
url.absoluteString
Related
This question already has answers here:
Firebase Storage Warning: downloadURL()' is deprecated: Use `StorageReference.downloadURLWithCompletion()
(2 answers)
Firebase Storage downloadURL()' is deprecated: Use `StorageReference.downloadURLWithCompletion()
(2 answers)
Closed 3 years ago.
I am using Xcode 10 and this method to upload a photo selected in the application to Firebase Storage. It is uploading the photo successfully, however, I am trying to get the download URL and populate it into a label on the same screen.
I have tried metadata.downloadURL but this throws an error metadata no longer recognises downloadURL in Xcode 10.
This is my function...
func uploadPhoto(completion: #escaping (_ url: String?) -> Void) {
let photoName = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("photoURL").child("\(photoName).jpg")
let photo = self.photoImageView.image!
if let uploadData = photo.jpegData(compressionQuality: 0.75) {
storageRef.putData(uploadData, metadata: nil) { (metadata, error) in
guard metadata != nil else {
// Uh-oh, an error occurred!
return
}
// Metadata contains file metadata such as size, content-type.
//let size = metadata?.size
// You can also access to download URL after upload.
storageRef.downloadURL { (url, error) in
guard url != nil else {
// Uh-oh, an error occurred!
return
}
// Metadata contains file metadata such as size, content-type, and download URL.
// THROWS ERROR
// let downloadURL = metadata.downloadURL
// MY ATTEMPT
var downloadURL = StorageReference.downloadURL(self.refStorage)
completion(downloadURL = self.urlLabel.text)
}
}
}
}
You need
storageRef.put(uploadData, metadata: nil, completion: { (metadata, error) in
if(error != nil){
print(error)
return
}
storageRef.downloadURL { url, error in
if let error = error {
// Handle any errors
if(error != nil){
print(error)
}
} else {
// Get the download URL for 'images/stars.jpg'
let urlStr:String = (url?.absoluteString) ?? ""
print(urlStr)
}
}
})
Just update new firebase, now I get the above error in the 10th line...
It worked under firebase 3 and 4, but as they deleted the downloadURL its not working in the fifth version anymore... please don't duplicate this question or similar as I already tried any solution on the internet and nothing worked...
fileprivate func handleVideoSelectedForUrl(_ url: URL) {
let filename = UUID().uuidString + ".mov"
let uploadTask = Storage.storage().reference().child("message_movies").child(filename).putFile(from: url, metadata: nil, completion: { (metadata, error) in
if error != nil {
print("Failed upload of video:", error!)
return
}
if let videoUrl = metadata?.downloadURL()?.absoluteString {
if let thumbnailImage = self.thumbnailImageForFileUrl(url) {
self.uploadToFirebaseStorageUsingImage(thumbnailImage, completion: { (imageUrl) in
let properties: [String: AnyObject] = ["imageUrl": imageUrl as AnyObject, "imageWidth": thumbnailImage.size.width as AnyObject, "imageHeight": thumbnailImage.size.height as AnyObject, "videoUrl": videoUrl as AnyObject]
self.sendMessageWithProperties(properties)
})
}
}
})
// In putData response closer You can get downloadURL with below updated code
metadata?.storageReference?.downloadURL(completion: { (url, error) in
print(url)
})
Before this You can retire like
metadata?.downloadURL()
I just updated Firebase Storage to 5.0.0 and it looks like metadata.downloadURL() is not recognized anymore. (Value of type 'StorageMetadata' has no member 'downloadURL')
Though after looking in the documentation it should still be available :
https://firebase.google.com/docs/reference/swift/firebasestorage/api/reference/Classes/StorageMetadata#/c:objc(cs)FIRStorageMetadata(im)downloadURL
The project was cleaned & rebuilt already.
Am I missing something ?
Can you try Google Firebase docs
// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")
// Fetch the download URL
starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors
} else {
// Get the download URL for 'images/stars.jpg'
}
}
This is my version for Swift 3 / Swift 4.
Explanation of what happens in the code.
This is essentially the same answer as Sh_Khan's. But in his example the User already knows the bucket path. In my example, we get the path from an upload task. This was what has lead me to this question as well as what I think op was looking for as he was looking for metadata.downloadURL() replacement.
class StorageManagager {
private let storageReference: StorageReference
init() {
// first we create a reference to our storage
// replace the URL with your firebase URL
self.storageReference = Storage.storage().reference(forURL: "gs://MYAPP.appspot.com")
}
// MARK: - UPLOAD DATA
open func uploadData(_ data: Data, named filename: String, completion: #escaping (URL? , Error?) -> Void) {
let reference = self.storageReference.child(filename)
let metadata = StorageMetadata()
metadata.contentType = "ourType" // in my example this was "PDF"
// we create an upload task using our reference and upload the
// data using the metadata object
let uploadTask = reference.putData(data, metadata: metadata) { metadata, error in
// first we check if the error is nil
if let error = error {
completion(nil, error)
return
}
// then we check if the metadata and path exists
// if the error was nil, we expect the metadata and path to exist
// therefore if not, we return an error
guard let metadata = metadata, let path = metadata.path else {
completion(nil, NSError(domain: "core", code: 0, userInfo: [NSLocalizedDescriptionKey: "Unexpected error. Path is nil."]))
return
}
// now we get the download url using the path
// and the basic reference object (without child paths)
self.getDownloadURL(from: path, completion: completion)
}
// further we are able to use the uploadTask for example to
// to get the progress
}
// MARK: - GET DOWNLOAD URL
private func getDownloadURL(from path: String, completion: #escaping (URL?, Error?) -> Void) {
self.storageReference.child(path).downloadURL(completion: completion)
}
}
Let's try this code in Swift 4.2:
let imgData = UIImage.jpegData(self.imageView.image!)
let imageName = UUID().uuidString
let ref = Storage.storage().reference().child("pictures/\(imageName).jpg")
let meta = StorageMetadata()
meta.contentType = "image/jpeg"
self.uploadToCloud(data: imgData(0.5)!, ref: ref, meta: meta)
UploadToCloud Method:
` Method UploadToCloud
func uploadToCloud(data:Data, ref:StorageReference, meta:StorageMetadata) {
ref.putData(data, metadata: meta) { (metaData, error) in
if let e = error {
print("==> error: \(e.localizedDescription)")
}
else
{
ref.downloadURL(completion: { (url, error) in
print("Image URL: \((url?.absoluteString)!)")
})
}
}
}
This question pops up for all language searches. Hence for Kotlin, the solution is something of the kind below:
val photoRef = FirebaseStorage.getInstance()
.reference.child("images/stars.jpg")
// Code ommited - Do some saving - putFile
photoRef.downloadUrl.addOnSuccessListener({ uri ->
product.imageUrl = uri.toString()
})
However, this is not a good solution. You are better off saving the path and then re-constructing the full Url on demand. For example:
photoRef.downloadUrl.addOnSuccessListener({ uri ->
val imagePath = uri.toString()
// Save to database
})
Now, you can use it later, and only on demand:
FirebaseStorage.getInstance().reference.child(product.imageUrl).downloadUrl
.addOnSuccessListener { uri ->
String imageUrl = uri.toString()
// Load in images
}
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
if error != nil {
print(error as Any)
return
}
guard let uid = user?.user.uid else {
return
}
self.dismiss(animated: true, completion: nil)
//Добавляем картинку в firebase. Надо добавить в Pods file pod 'Firebase/Storage' и запустить терминал
let imageName = NSUUID().uuidString
let storageRef = Storage.storage().reference()
// Create a reference to the file you want to download
let starsRef = storageRef.child("profile_images").child("\(imageName).png")
let uploadData = self.profileImageView.image?.pngData()
starsRef.putData(uploadData!, metadata: nil, completion: { (metadata, error) in
if error != nil {
print(error as Any)
}
if let profileImageUrl = metadata?.path {
let values = ["name": name, "email": email, "profileImage": profileImageUrl]
self.registerUserIntoDatabaseWithUID(uid: uid, values: values)
}
})
}
If you are stuck in converting URL to string... you can try this
url.absoluteString
I just updated Firebase Storage to 5.0.0 and it looks like metadata.downloadURL() is not recognized anymore. (Value of type 'StorageMetadata' has no member 'downloadURL')
Though after looking in the documentation it should still be available :
https://firebase.google.com/docs/reference/swift/firebasestorage/api/reference/Classes/StorageMetadata#/c:objc(cs)FIRStorageMetadata(im)downloadURL
The project was cleaned & rebuilt already.
Am I missing something ?
Can you try Google Firebase docs
// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")
// Fetch the download URL
starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors
} else {
// Get the download URL for 'images/stars.jpg'
}
}
This is my version for Swift 3 / Swift 4.
Explanation of what happens in the code.
This is essentially the same answer as Sh_Khan's. But in his example the User already knows the bucket path. In my example, we get the path from an upload task. This was what has lead me to this question as well as what I think op was looking for as he was looking for metadata.downloadURL() replacement.
class StorageManagager {
private let storageReference: StorageReference
init() {
// first we create a reference to our storage
// replace the URL with your firebase URL
self.storageReference = Storage.storage().reference(forURL: "gs://MYAPP.appspot.com")
}
// MARK: - UPLOAD DATA
open func uploadData(_ data: Data, named filename: String, completion: #escaping (URL? , Error?) -> Void) {
let reference = self.storageReference.child(filename)
let metadata = StorageMetadata()
metadata.contentType = "ourType" // in my example this was "PDF"
// we create an upload task using our reference and upload the
// data using the metadata object
let uploadTask = reference.putData(data, metadata: metadata) { metadata, error in
// first we check if the error is nil
if let error = error {
completion(nil, error)
return
}
// then we check if the metadata and path exists
// if the error was nil, we expect the metadata and path to exist
// therefore if not, we return an error
guard let metadata = metadata, let path = metadata.path else {
completion(nil, NSError(domain: "core", code: 0, userInfo: [NSLocalizedDescriptionKey: "Unexpected error. Path is nil."]))
return
}
// now we get the download url using the path
// and the basic reference object (without child paths)
self.getDownloadURL(from: path, completion: completion)
}
// further we are able to use the uploadTask for example to
// to get the progress
}
// MARK: - GET DOWNLOAD URL
private func getDownloadURL(from path: String, completion: #escaping (URL?, Error?) -> Void) {
self.storageReference.child(path).downloadURL(completion: completion)
}
}
Let's try this code in Swift 4.2:
let imgData = UIImage.jpegData(self.imageView.image!)
let imageName = UUID().uuidString
let ref = Storage.storage().reference().child("pictures/\(imageName).jpg")
let meta = StorageMetadata()
meta.contentType = "image/jpeg"
self.uploadToCloud(data: imgData(0.5)!, ref: ref, meta: meta)
UploadToCloud Method:
` Method UploadToCloud
func uploadToCloud(data:Data, ref:StorageReference, meta:StorageMetadata) {
ref.putData(data, metadata: meta) { (metaData, error) in
if let e = error {
print("==> error: \(e.localizedDescription)")
}
else
{
ref.downloadURL(completion: { (url, error) in
print("Image URL: \((url?.absoluteString)!)")
})
}
}
}
This question pops up for all language searches. Hence for Kotlin, the solution is something of the kind below:
val photoRef = FirebaseStorage.getInstance()
.reference.child("images/stars.jpg")
// Code ommited - Do some saving - putFile
photoRef.downloadUrl.addOnSuccessListener({ uri ->
product.imageUrl = uri.toString()
})
However, this is not a good solution. You are better off saving the path and then re-constructing the full Url on demand. For example:
photoRef.downloadUrl.addOnSuccessListener({ uri ->
val imagePath = uri.toString()
// Save to database
})
Now, you can use it later, and only on demand:
FirebaseStorage.getInstance().reference.child(product.imageUrl).downloadUrl
.addOnSuccessListener { uri ->
String imageUrl = uri.toString()
// Load in images
}
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
if error != nil {
print(error as Any)
return
}
guard let uid = user?.user.uid else {
return
}
self.dismiss(animated: true, completion: nil)
//Добавляем картинку в firebase. Надо добавить в Pods file pod 'Firebase/Storage' и запустить терминал
let imageName = NSUUID().uuidString
let storageRef = Storage.storage().reference()
// Create a reference to the file you want to download
let starsRef = storageRef.child("profile_images").child("\(imageName).png")
let uploadData = self.profileImageView.image?.pngData()
starsRef.putData(uploadData!, metadata: nil, completion: { (metadata, error) in
if error != nil {
print(error as Any)
}
if let profileImageUrl = metadata?.path {
let values = ["name": name, "email": email, "profileImage": profileImageUrl]
self.registerUserIntoDatabaseWithUID(uid: uid, values: values)
}
})
}
If you are stuck in converting URL to string... you can try this
url.absoluteString
I'm trying to create a function that uploads images to Firebase Storage and returns the download url for their path so I can use it other parts of the app.
This is what the function looks like:
func uploadImage(to reference:StorageReference, image:UIImage) -> URL? {
let imageData = UIImageJPEGRepresentation(image, 0.2)
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
var downloadURL = metadata.downloadURL()
reference.putData(imageData!, metadata: metadata) { (metadata, error) in
if error != nil {
print("Couldnt upload due to \(String(describing: error))")
}
downloadURL = metadata?.downloadURL()
}
return downloadURL!
}
I can't seem to get the result that I want as downloadUrl always returns nil. What am I doing wrong?
The problem here is that your function is returning before the upload is complete. In other words your function needs to return a callback, rather than a plain URL. Something like -
func uploadImage(to reference:StorageReference, image:UIImage, completion: #escaping (URL?) -> Void) {
let imageData = UIImageJPEGRepresentation(image, 0.2)
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
var downloadURL = metadata.downloadURL()
reference.putData(imageData!, metadata: metadata) { (metadata, error) in
if error != nil {
print("Couldnt upload due to \(String(describing: error))")
completion(nil)
} else {
if let downloadUrl = metadata?.downloadURL() {
completion(downloadUrl)
} else {
completion(nil)
}
}
}
}