I just updated my project to the latest version of Firebase Storage and I am now getting a warning:
downloadURL() is deprecated: Use StorageReference.downloadURLWithCompletion() to obtain a current download URL.
I looked at the Firebase image upload documentation but it still references using downloadURL() which is now depreciated. In the code below I am getting the download URL of the image as a String. The code works but now to be updated since downloadURL() is depreciated
uploadProfilePicTask.observe(.success) { snapshot in
guard let profilePicStringURL = snapshot.metadata?.downloadURL()?.absoluteString else { return }
...
Here is my attempted updated. I tried the code below with the new downloadURLWithCompletion() but something in snapshot.metadata?.storageReference? is returning nil so I am not able to retrieve the url String. Does anyone know how to use the new downloadURLWithCompletion() appropriately below?
uploadProfilePicTask.observe(.success) { snapshot in
snapshot.metadata?.storageReference?.downloadURL { URL, error in
if let urlString = URL?.absoluteString {
// Do something
} else {
return
}
}
Basically not using the metadata but instead just getting the url after the success of your observe event. Since it's successful and you know it's there, you can download the URL. It's there in their docs to 'Generate a download URL'. Below, I'm assuming your StorageReference is uploadProfilePicTask.
uploadProfilePicTask.downloadURL(completion: { (url, error) in
if (error == nil) {
if let downloadUrl = url {
// Make you download string
let downloadString = downloadUrl.absoluteString
}
} else {
// Do something if error
}
})
I had the same problem, but I fixed it with this code:
uploadTask.observe(.success) { snapshot in
guard let imageURL = snapshot.metadata?.storageReference?.downloadURL(completion: { (url, error) in if error != nil {
print(error as Any)
} else { //add all you want
}
}) else { return }
let imageStr = String(describing: imageURL)
DBService.manager.updatePhoto(profileImageUrl: imageStr)
AuthService.manager.updatePhoto(urlString: imageStr)
}
}
Related
I need to display the images that have been stored on the storage on Firebase. Right now, I only tracked the images using the link generated by function downloadURL:
func UploadImage(imageData: Data, path: String, completion: #escaping (String) -> ()){
let storage = Storage.storage().reference()
let uid = Auth.auth().currentUser?.uid
storage.child(path).child(uid ?? "").putData(imageData, metadata: nil) { (_, err) in
if err != nil{
completion("")
return
}
// Downloading Url And Sending Back...
storage.child(path).child(uid ?? "").downloadURL { (url, err) in
if err != nil{
completion("")
return
}
completion("\(url!)")
}
}
}
So all I can get is a hyperlink that is like: https://firebasestorage.googleapis.com/v0/b/getting-started-20f2f.appspot.com/o/profile_Photos%2FGQ1KR9H1mLZl2NAw9KQcRe7d72N2?alt=media&token=473ce86c-52ba-42ec-be71-32cc7dc895d7.
I refer to the official documentation, it seems that only when I have the name of the image file can I download it to an ImageView or UIImageView object. However, the link does not make any sense to me, so what can I do?
EDIT
I actually tried a solution provided by the official documentation:
func imageDownloader(_ imageURL: String) {
let store = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
let imageRef = store.child(imageURL)
var myImageView = UIImageView()
imageRef.getData(completion: { (error, data) in
if let error = error {
// Uh-oh, an error occurred!
} else {
// Data for "images/island.jpg" is returned
let image = UIImage(data: data!)
}
})
}
But it suggests that I need to change something because Cannot convert value of type 'DataSnapshot' to expected argument type 'Data'.
If you're storing the image paths in Firestore, actually the exact file name does not matter if there is only one file available under the fork. So you just need to specify the path.
To then download the image from Storage, construct the path and download:
let uid = Auth.auth().currentUser?.uid
Storage.storage().reference().child("the\path\to\your\uid\collection").child(uid).getData(maxSize: 1048576, completion: { (data, error) in
if let data = data,
let img = UIImage(data: data) {
// do something with your image
} else {
if let error = error {
print(error)
}
// handle errors
}
})
You are uploading to Storage.storage(), but then in your imageDownloader, you're attempting to use Database.database(), which has a similar-looking API, but is, in fact, different.
Make sure to use Storage.storage() and that the closure parameters are in the order data, error in.
Finally, right now in your imageDownloader, it doesn't look like you're doing anything yet with var myImageView = UIImageView(), but keep in mind that you won't have access to the UIImage until the async getData completes.
Store your images at Firebase Storage & then retrieve using this code.
Storage.storage().reference.child("ProfilePhotos").child("ImageName").downloadURL {(url, _) in
DispatchQueue.main.async {
guard let url = url else { return }
imageView.setImage(with: url, placeholder: UIImage(named: "dummyImage"))
}
}
Currently, I can fetch the download url by file name via firebase storage reference.
I would like to retrieve all download URLS in a specific child without using a file name and only using the last child name.
Simply adding every download url in a list/array
How can I accomplish this with my given reference.
func getDownloadURL() {
let ref = Storage.storage().reference()
let fileName = "Lessons_Lesson1_Class1.mp3"
let starsRef = ref.child("Daily Meditations").child("Lessons").child("Lesson 1").child(fileName)
// Fetch the download URL
starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors
print(error)
} else {
// Get the download URL for 'Lessons_Lesson1_Class1.mp3'
print(url)
}
}
}
Firebase Refrence Docs
let stg = Storage.storage().reference()
let path = "Daily Meditations/Lessons/Lesson 1"
stg.child(path).listAll { (list, error) in
if let error = error {
print(error)
} else {
let inStorage = list.items.map({ $0.name })
print(inStorage) // an array of file names in string format
}
}
I assume spaces are allowed in path names since you're using them. To list all of the files in a path, use listAll. The method will return a StorageListResult object which I've named list.
https://firebase.google.com/docs/reference/swift/firebasestorage/api/reference/Classes/StorageListResult
So I was able to combine List all files and Download URL to achieve what I was trying to accomplish from the firebase documentation.
Here is the code:
func getDownloadURl() {
let ref = Storage.storage().reference()
let storageReference = ref.child("Lessons/Lesson 1")
storageReference.listAll { (result, error) in
if let error = error {
print(error)
}
for item in result.items {
//List storage reference
let storageLocation = String(describing: item)
let gsReference = Storage.storage().reference(forURL: storageLocation)
// Fetch the download URL
gsReference.downloadURL { url, error in
if let error = error {
// Handle any errors
print(error)
} else {
// Get the download URL for each item storage location
print(url!)
}
}
}
}
}
If anyone is using with VUE 2.6 and TS, here is my workaround
Imports
import {
getStorage,
ref,
getDownloadURL,
listAll,
StorageReference,
} from "firebase/storage";
async mounted(): Promise<void> {
const storage = getStorage();
const imageRefs = await listAll(ref(storage, "SOME BUCKET"))
.then((refs) => {
return refs.items;
})
.catch((error) => {
// Handle any errors
});
(imageRefs as StorageReference[]).forEach((item) => {
console.log(item);
getDownloadURL(item).then((downloadURL) => {
console.log(downloadURL);
this.model.listFiles.push(downloadURL);
});
});
console.log(imageRefs);
console.log(this.model.listFiles);
},
Hi I have Question about making ios Application wiht Firebase
Nowadays I am making a chat Application using watching an YouTube
https://www.youtube.com/watch?v=MJ1r5jjdf4Q&index=4&list=PLmdU__e_zPf9uczwNhLNANvxT5mzxMiXQ
In here
At the Source code, let imageUrl = data?.downloadURL()?.absoluteString this got an error "Value of type 'StorageMetadata' has no member 'downloadURL'"
I heard the downloadURL() was deprecated in Firebase So, docs said using StorageReference.downloadURLWithCompletion() instead of downloadURL.
But I don't know how to change the code.
Please tell me how to change the code. And chage the code
Thank you!
func signupEvent(){
Auth.auth().createUser(withEmail: email.text!, password: password.text!){(user,err) in
let uid = user?.user.uid
let image = UIImageJPEGRepresentation(self.imageView.image!, 0.1)
Storage.storage().reference().child("userImage").child(uid!).putData(image!, metadata:nil, completion:{(data, error) in
let imageUrl = data?.downloadURL()?.absoluteString
Database.database().reference().child("users").child(uid).setValue(["name": self.name.text!, "profileImageUrl" : imageUrl])
})
}
}
You can check the updated documentation of Firebase 5 upload files here, the API changed so you should use StorageReference's downloadURL method.
So your code become something like this:
func signupEvent(){
Auth.auth().createUser(withEmail: email.text!, password: password.text!){(user,err) in
let uid = user?.user.uid
let image = UIImageJPEGRepresentation(self.imageView.image!, 0.1)
let storageItem = Storage.storage().reference().child("userImage").child(uid!)
storageItem.putData(image!, metadata:nil, completion:{(data, error) in
// Now is good to check errors
if error != nil {
print("Error: couldn't upload the image")
}
else {
storageItem.downloadURL(completion: { (url, error) in
if error != nil {
print(error!)
return
}
if url != nil {
let imageUrl = url!.absoluteString
Database.database().reference().child("users").child(uid).setValue(["name": self.name.text!, "profileImageUrl" : imageUrl])
}
}
}
})
}
}
I am currently learning about how to upload/download images to/from Firebase. However, I am encountering two problems:
When I upload the image to my Firebase console it says it's type is "application/octet-stream" which is not exactly what I want (I uploaded a jpeg file)
Here's the code:
#IBAction func completeSignUpButton(_ sender: UIButton) {
let userProfileImageRef = storage.child("userProfileImage")
//UPloading the photo into firebase
let data = Data()
//uploading user profile picture
if self.userInitialPhoto.image != nil {
if let uploadData = UIImagePNGRepresentation(self.userInitialPhoto.image!) {
userProfileImageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if error != nil {
print(error?.localizedDescription)
return
} else {
print("Image upload success!")
//self.dismiss(animated: true, completion: nil)
self.performSegue(withIdentifier: "completeRegistrationSegue", sender: self)
}
})
}
} else {
print("You need to pick a picture!")
}
}
So this might be the problem that's causing my second problem:
When I try to load the image from Firebase to my UIImage in my app, it says Object Optional(\"userID\")/userProfileImage does not exist."
Here's my code for that:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
docRef = Firestore.firestore().collection("user Status").document("Current Status")
self.userStatusTableView.reloadData()
let referencePath = Storage.storage().reference(withPath: "\(userID)/userProfileImage")
let userProfileImageRef = Storage.storage().reference().child("\(userID)/userProfileImage")
userProfileImageRef.getData(maxSize: 1 * 1024 * 1024) { (data, error) in
if error != nil {
print("There's an eror downloading the image\(error?.localizedDescription)")
} else {
self.userProfileImage.image = UIImage(data: data!)
}
}
}
I am wondering what I should do to fix these issues.
Thanks for your help in advance and happy new year to you all.
while uploading the image to firebase you passed metadata as nil. you need to pass image metadata there
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
and in upload complitionBlock, you can get URL for that image using
if error == nil , let meta = meta {
if let url = meta.downloadURL()?.absoluteString {
//use this url to access your image
}
}
Using IOS 9.1, running on Xcode 7.1.1. under El Capitan. I am trying out the tutorial on accessing dropbox thru their (new maybe) SwiftDropbox library by following this page.
https://blogs.dropbox.com/developers/2015/05/try-out-swiftydropbox-the-new-swift-sdk-for-dropbox-api-v2/
Started well, managed to connect and get authorised, but unable to do much more cause the code posted to their tutorial doesn't compile.
if let client = Dropbox.authorizedClient {
// Get the current user's account info
client.usersGetCurrentAccount().response { response, error in
if let account = response {
println("Hello \(account.name.givenName)")
} else {
println(error!)
}
}
// List folder
client.filesListFolder(path: "").response { response, error in
if let result = response {
println("Folder contents:")
for entry in result.entries {
println(entry.name)
}
} else {
println(error!)
}
}
Complaining that DropboxClient has no member "usersGetCurrentAccount" or "filesListFolder" which I assume are some sort method calls {pretty new to swift too}. Can not seem to google any useful leads on this? What should this code read/say?
Bon,
THANKYOU smarx; you put me on the right path. Here is the final code; with two minor fixes to the tutorial he mentioned here.
// ViewController.swift
import UIKit
import SwiftyDropbox
class ViewController: UIViewController {
#IBAction func linkButtonPressed(sender: AnyObject) {
if (Dropbox.authorizedClient == nil) {
Dropbox.authorizeFromController(self)
} else {
print("User is already authorized!")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Verify user is logged into Dropbox
if let client = Dropbox.authorizedClient {
// Get the current user's account info
client.users.getCurrentAccount().response { response, error in
print("*** Get current account ***")
if let account = response {
print("Hello \(account.name.givenName)!")
} else {
print(error!)
}
}
// List folder
client.files.listFolder(path: "").response { response, error in
print("*** List folder ***")
if let result = response {
print("Folder contents:")
for entry in result.entries {
print(entry.name)
}
} else {
print(error!)
}
}
// Upload a file
let fileData = "Hello!".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
client.files.upload(path: "/hello.txt", body: fileData!).response { response, error in
if let metadata = response {
print("*** Upload file ****")
print("Uploaded file name: \(metadata.name)")
print("Uploaded file revision: \(metadata.rev)")
// Get file (or folder) metadata
client.files.getMetadata(path: "/hello.txt").response { response, error in
print("*** Get file metadata ***")
if let metadata = response {
if let file = metadata as? Files.FileMetadata {
print("This is a file with path: \(file.pathLower)")
print("File size: \(file.size)")
} else if let folder = metadata as? Files.FolderMetadata {
print("This is a folder with path: \(folder.pathLower)")
}
} else {
print(error!)
}
}
// Download a file
let destination : (NSURL, NSHTTPURLResponse) -> NSURL = { temporaryURL, response in
let fileManager = NSFileManager.defaultManager()
let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
// generate a unique name for this file in case we've seen it before
let UUID = NSUUID().UUIDString
let pathComponent = "\(UUID)-\(response.suggestedFilename!)"
return directoryURL.URLByAppendingPathComponent(pathComponent)
}
client.files.download(path: "/hello.txt", destination: destination).response { response, error in
//client.files.download(path: "/hello.txt").response { response, error in
if let (metadata, url) = response {
print("*** Download file ***")
let data = NSData(contentsOfURL: url)
print("Downloaded file name: \(metadata.name)")
print("Downloaded file url: \(url)")
print("Downloaded file data: \(data)")
} else {
print(error!)
}
}
} else {
print(error!)
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You're reading a blog post from May about an early preview version of the SDK. Lots of things have changed since that post! Check out https://www.dropbox.com/developers/documentation/swift#tutorial for an up-to-date tutorial.
I believe you want users.getCurrentAccount and files.listFolder.