how to read the url string of uploaded image in a view? - ios

this is the upload image function is inside the view
private func persistImageToStorage() {
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Storage.storage().reference(withPath: uid)
guard let imageData = self.image?.jpegData(compressionQuality: 0.5) else { return }
ref.putData(imageData, metadata: nil) { metadata, err in
if let err = err {
self.loginStatusMessage = "Failed to push image to Storage: \(err)"
return
}
ref.downloadURL { url, err in
if let err = err {
self.loginStatusMessage = "Failed to retrieve downloadURL: \(err)"
return
}
self.loginStatusMessage = "Successfully stored image with url: \(url?.absoluteString ?? "")"
print(url?.absoluteString as Any)
}
}
}
i want to read the url?.absoluteString in its view and all the functions within the view ? how can i extract that url?.absoluteString to be read ?
if you could kindly show me the way, thank you alot

Related

Not able to get the url of uploaded image on firebase storage

class FCMStorage {
var storage: Storage!
init() {
storage = Storage.storage()
}
func storeImage(data: Data?, name: String, completion: #escaping ((String?, Error?)->Void)) {
guard let data = data else {
return
}
let metaData = StorageMetadata()
metaData.contentType = "image/jpeg"
let path = "images/" + name
print("img to store = \(path)")
let ref = storage.reference()
let uploadTask = ref.child(path).putData(data, metadata: metaData) { (metadata, error) in
if error == nil {
print(metadata as Any)
ref.downloadURL(completion: { (url, error) in
completion(url?.absoluteString, error)
})
} else {
print("storeImage error: \(error!)")
}
}
uploadTask.observe(.progress) { (snapshot) in
print((snapshot.progress?.fractionCompleted ?? 0) * 100.0)
if snapshot.status == .success || snapshot.status == .failure {
uploadTask.removeAllObservers(for: .progress)
}
}
}
}
Using the able class I am able to upload the image on firebase successfully and I am able to see the uploaded image on the firebase too but...
When I call downloadURL() method it always giving me the following error
ref.downloadURL(completion: { (url, error) in
completion(url?.absoluteString, error)
})
Error: Failed to retrieve a download URL.
Anyone could help me out on this issue!!
EDIT
When I print metadata of the file it prints the following....
FIRStorageMetadata 0x283f99860: {
bucket = "sportoilic.appspot.com";
contentDisposition = "inline; filename*=utf-8''8E13A816-FAF1-47ED-8F84-94BBB8C4C77F";
contentEncoding = identity;
contentType = "application/octet-stream";
generation = 1601287237056536;
md5Hash = "VgMH6NMPGJT//LCD8goaDA==";
metageneration = 1;
name = "8E13A816-FAF1-47ED-8F84-94BBB8C4C77F";
size = 114787;
timeCreated = "2020-09-28T10:00:37.056Z";
updated = "2020-09-28T10:00:37.056Z";
}
and after that when I try to get the download url for the uploaded image< I am getting the above mentioned error(Error: Failed to retrieve a download URL).
What is the issue? Am I missing something here?
After trial and error of several hours, finally got the solution.
class FCMStorage {
var ref: StorageReference!
init(path: String) {
ref = Storage.storage().reference(withPath: path)
print("img to store at path = \(path)")
}
func storeImage(data: Data?, completion: #escaping ((String?, Error?)->Void)) {
guard let data = data else {
return
}
let uploadTask = ref.putData(data, metadata: nil) { (metadata, error) in
if error == nil {
print(metadata as Any)
self.ref.downloadURL(completion: { (url, error) in
completion(url?.absoluteString, error)
})
} else {
print("storeImage error: \(error!)")
}
}
uploadTask.observe(.progress) { (snapshot) in
print((snapshot.progress?.fractionCompleted ?? 0) * 100.0)
if snapshot.status == .success || snapshot.status == .failure {
uploadTask.removeAllObservers(for: .progress)
}
}
}
}
So store image just need to call like this...
let path = "images/" + UUID().uuidString
FCMStorage(path: path).storeImage(data: data) { (imgUrl, error) in
if let strUrl = imgUrl, error == nil {
FCMDatabase.init(OfTable: .chatRooms).setImageUrl(strUrl: strUrl, teamId: self.team?.id ?? 0, forMsgId: self.arrChats.last?.messageId ?? "") { (isDone) in
if isDone {
print("Image url set in database")
}
}
} else {
print("Error: \(error?.localizedDescription ?? "Error while getting image url")")
}
}

How to upload an array of images in Firebase Storage using iOS Swift

I want to upload an array of images by user
This is the code when i am uploading a single image to firebase storage refer Code: 1. but i am having problem when i am uploading and array of image. Refer code: 2
Code: 1
func uploadImage(image:UIImage,userId:String,completion:#escaping(_ status:Bool,_ response:String)->Void){
// if status is true then downloadurl will be in response
// Data in memory
guard let data = image.jpegData(compressionQuality: 0.2) else{
completion(false,"Unable to get data from image")
return
}
// Create a reference to the file you want to upload
let riversRef = firebaseStorage.reference().child("images/\(userId).jpg")
// Upload the file to the path "images/rivers.jpg"
let _ = riversRef.putData(data, metadata: nil) { (metadata, error) in
guard let _ = metadata else{
// Uh-oh, an error occurred!
completion(false,error!.localizedDescription)
return
}
// You can also access to download URL after upload.
riversRef.downloadURL { (url, error) in
guard let downloadURL = url else{
// Uh-oh, an error occurred!
completion(false,error!.localizedDescription)
return
}
completion(true,downloadURL.absoluteString)
}
}
}
Code: 2
func uploadPostImages(image:[UIImage],userId:String,completion:#escaping(_ status:Bool,_ response:String)->Void){
let photoDictionary = ["postImages": PostArray.sharedInstance.photosArray as NSArray]
// Create a reference to the file you want to upload
let riversRef = firebaseStorage.reference().child("postImages/\(userId).jpg")
// Upload the file to the path "images/rivers.jpg"
let _ = riversRef.putData(photoDictionary, metadata: nil) { (metadata, error) in
guard let _ = metadata else{
// Uh-oh, an error occurred!
completion(false,error!.localizedDescription)
return
}
// You can also access to download URL after upload.
riversRef.downloadURL { (url, error) in
guard let downloadURL = url else{
// Uh-oh, an error occurred!
completion(false,error!.localizedDescription)
return
}
completion(true,downloadURL.absoluteString)
}
}
}
I am getting this error in code: 2
Cannot convert value of type '[String : NSArray]' to expected argument type 'Data'
anyone who can help me??
To my knowledge something like this should work. Sorry, I am not at an IDE. If this doesn't work leave a comment and I will take a closer look.
func uploadImages(
images:[UIImage],
userId:String,
completion:#escaping(_ status:Bool,_ response:String)->Void)
{
images.enumerated().forEach { (index, image) in
guard let data = image.jpegData(compressionQuality: 0.2) else{
completion(false,"Unable to get data from image")
return
}
// Create a reference to the file you want to upload
let riversRef = firebaseStorage.reference().child("images/\(userId)\(index).jpg")
// Upload the file to the path "images/rivers.jpg"
let _ = riversRef.putData(data, metadata: nil) { (metadata, error) in
guard let _ = metadata else{
// Uh-oh, an error occurred!
completion(false,error!.localizedDescription)
return
}
// You can also access to download URL after upload.
riversRef.downloadURL { (url, error) in
guard let downloadURL = url else{
// Uh-oh, an error occurred!
completion(false,error!.localizedDescription)
return
}
completion(true,downloadURL.absoluteString)
}
}
}
}
This code will upload an array of images
func uploadImages(images:[UIImage], userId:String, completion:#escaping(_ status:Bool, _ response:String)->Void){
guard images.count <= 5 && !images.isEmpty else {return}
convertImagesToData(images: images).enumerated().forEach { (index, image) in
let riversRef = firebaseStorage.reference().child("userAdPostImages/\(userId)\(index).jpg")
let _ = riversRef.putData(image, metadata: nil, completion: { (_ , error) in
if let error = error {
completion(true, error.localizedDescription)
return
}
riversRef.downloadURL(completion: {(url, error) in
if let error = error{
completion(true,error.localizedDescription)
return
}
guard let downloadURL = url else {return}
completion(false,downloadURL.absoluteString)
})
})
}
}
and this will add your post to firebase including array images
func addPost() {
hud.show()
dispatchGroup.enter()
let user = Auth.auth().currentUser
if let user = user {
self.userId = user.uid
}
let location = self.locationTextfield.text ?? ""
let type = self.selectedType ?? ""
let description = self.descriptionTextView.text ?? ""
let adImages = self.adImages
let userId = self.userId ?? ""
let price = priceTextfield.text ?? ""
let userName = self.userName ?? ""
let userProfileImage = self.userProfileImage ?? ""
let userphoneNumber = self.phoneNumber ?? ""
ServerManager.sharedDelegate.uploadImages(images: adImages, userId: userId) { (isError, urlString) in
guard !isError else {
DispatchQueue.main.async {
hud.hide()
}
return
}
self.imagePaths.append(urlString)
print("This is the image path saved \(self.imagePaths)!!!!")
if self.imagePaths.count == adImages.count {
self.dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .global(qos: .background), execute: {
ServerManager.sharedDelegate.addPost(UserProfileImage: userProfileImage, UserName: userName, phoneNumber: userphoneNumber, adImages: self.imagePaths, Price: price, location: location, type: type, Description: description) { _ , message in
DispatchQueue.main.async {
hud.hide()
self.vc?.view.makeToast(message)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.vc?.dismiss(animated: true, completion: nil)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
}
}
return
}
})
}
Thanks to #MichaelWells for help and sorry for late posting the answer
You can encode the dict and then store it as data:
let data = JSONEncoder().encode(photoDictionary)

Uploading multiple files to Firebase Storage Very Slow

I am trying to upload two files to firebase storage at the same time. From what I understand this is not possible so what I did was try to upload one first and then the next file once the first is done.
It is working now, however the upload speed is very slow. Is this because of an issue with my code or is it because Im waiting for two uploads as opposed to one.
var index = 0
var urls = [String]()
fileprivate func uploadToServer(data: Any) {
if index == 0 {
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("posts").child(filename)
storageRef.putData(data as! Data, metadata: nil) { (metadata, err) in
if let err = err {
self.navigationItem.rightBarButtonItem?.isEnabled = true
print("Failed to upload post image:", err)
self.showHUDwithError(error: err)
return
}
storageRef.downloadURL(completion: { (downloadURL, err) in
if let err = err {
print("Failed to fetch downloadURL:", err)
self.showHUDwithError(error: err)
return
}
guard let thisUrl = downloadURL?.absoluteString else { return }
self.urls.append(thisUrl)
self.index = self.index + 1
if self.type == "image" {
// we are done then so do the save to server call here
self.saveToDatabaseWithImageUrl()
} else {
self.uploadToServer(data: self.videoUrl as Any)
}
})
}
return
}
if index == 1 {
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("posts").child(filename)
storageRef.putFile(from: data as! URL, metadata: nil) { (metadata, err) in
if let err = err {
self.navigationItem.rightBarButtonItem?.isEnabled = true
print("Failed to upload post image:", err)
self.showHUDwithError(error: err)
return
}
storageRef.downloadURL(completion: { (downloadURL, err) in
if let err = err {
print("Failed to fetch downloadURL:", err)
self.showHUDwithError(error: err)
return
}
guard let thisUrl = downloadURL?.absoluteString else { return }
self.urls.append(thisUrl)
self.saveToDatabaseWithImageUrl()
self.index = 0
})
}
}
}

How to store images in firebase storage and save link to them on database?

I have looked around for an answer to this. The closest I got is here, however, It does not exactly answer my question. That being, how to store a reference to images which are saved in firebase storage, in the database.
Below is the code I have tried. It is able to store one image when uploaded but I am unsure as to whether this is what they mean by storing the reference.
if let imageData = UIImageJPEGRepresentation(image, 0.8) {
let metadata = storageRef //.child("poop/")
let uploadTask = metadata.putData(imageData, metadata: nil) {
(metadata, error) in
guard let metadata = metadata else {
// Uh-oh, an error occurred!
return
}
// You can also access to download URL after upload.
storageRef.downloadURL {
(url, error) in
guard let downloadURL = url else {
// Uh-oh, an error occurred!
return
}
//let imgURL = url
//database integration
let ref = Database.database().reference()
let usersRef = ref.child("usersPosts")
let uid = Auth.auth().currentUser?.uid
let newUserRef = usersRef.child(uid!)
//creates a child for email and password (i think we shud store password so we can tell sumone what it is inmediatly, maybe)
newUserRef.setValue(["Image": "\(downloadURL)"])
}
}
// let imgURL = storageRef.downloadURL
//
// //database integration
// let ref = Database.database().reference()
// let usersRef = ref.child("usersPosts")
//
// let uid = Auth.auth().currentUser?.uid
// let newUserRef = usersRef.child(uid!)
// //creates a child for email and password (i think we shud store password so we can tell sumone what it is inmediatly, maybe)
//// newUserRef.setValue(["Image": "\(imgURL)"])
// For progress
uploadTask.observe(.progress, handler: { (snapshot) in
guard let progress = snapshot.progress else {
return
}
let percentage = (Float(progress.completedUnitCount) / Float(progress.totalUnitCount))
progressBlock(Double(percentage))
})
} else {
completionBlock(nil, "Image could not be converted to Data.")
}
I appreciate the help!
Please modify your code as required
var imgData: NSData = NSData(data: UIImageJPEGRepresentation((self.img_Photo?.image)!, 0.8)!)
self.uploadProfileImageToFirebase(data: imgData)
func uploadProfileImageToFirebase(data:NSData){
let storageRef = Storage.storage().reference().child("usersPosts").child("\(uid).jpg")
if data != nil {
storageRef.putData(data as Data, metadata: nil, completion: { (metadata, error) in
if(error != nil){
print(error)
return
}
guard let userID = Auth.auth().currentUser?.uid else {
return
}
// Fetch the download URL
storageRef.downloadURL { url, error in
if let error = error {
// Handle any errors
if(error != nil){
print(error)
return
}
} else {
// Get the download URL for 'images/stars.jpg'
let urlStr:String = (url?.absoluteString) ?? ""
let values = ["downloadURL": urlStr]
self.addImageURLToDatabase(uid: userID, values: values as [String : AnyObject])
}
}
})
}
}
func addImageURLToDatabase(uid:String, values:[String:AnyObject]){
let ref = Database.database().reference(fromURL: "https://exampleapp.firebaseio.com/")
let usersReference = ref.child("usersPosts").child((Auth.auth().currentUser?.uid)!)
usersReference.updateChildValues(values) { (error, ref) in
if(error != nil){
print(error)
return
}
self.parentVC?.dismiss(animated: true, completion: nil)
}
}
(TS)
onFileChanged(param){
var aa;
const file: File = param.target.files[0];
const metaData = { 'contentType': file.type };
const StorageRef: firebase.storage.Reference = firebase.storage().ref('/photos/Category/'+this.CategoryName);
const Store = StorageRef.put(file, metaData);
setTimeout(() => {
const UP: firebase.storage.UploadTask = Store;
UP.snapshot.ref.getDownloadURL().then(function (downloadURL) {
console.log('File available at', downloadURL);
aa = downloadURL;
});
}, 1000);
setTimeout(() => {
this.ImageLink = aa;
debugger;
}, 2000);
IN HTML
type="file" accept="image/*" #file style="display: none">
<img (click)="file.click()" style="margin-left: 10%"src="http://icons.iconarchive.com/icons/icons8/windows-8/512/Photo-Video-Stack-Of-Photos-icon.png" width="50px" />
import * as firebase as '#ionic/firebase'

Display uploaded image using the new Firebase. swift 4

How can I download the image I uploaded in Firebase?
Here is how I upload my images:
func uploadProfileImage(_ image:UIImage, completion: #escaping ((_ url:URL?)->())) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let storage = Storage.storage()
let storageRef = storage.reference().child("user/\(uid)")
guard let imageData = UIImageJPEGRepresentation(image, 0.75) else { return }
let metaData = StorageMetadata()
metaData.contentType = "image/jpg"
storageRef.putData(imageData, metadata: metaData) { metaData, error in
if let error = error {
print(error.localizedDescription)
return
}
storageRef.downloadURL(completion: { (url, error) in
if let _ = error{
return
}
if url != nil{
completion(url)
}
})
}
}
func saveProfile(username:String, profileImageURL:URL, completion: #escaping ((_ success:Bool)->())) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let databaseRef = Database.database().reference().child("users/profile/\(uid)")
let userObject = [
"username": username,
"photoURL": profileImageURL.absoluteString ] as [String:Any]
databaseRef.setValue(userObject) { error, ref in
completion(error == nil)
}
}
But I'm not sure how I could download and display it. Any pointers?
Thank you in advance.

Resources