Uploading images to firebaseStorage - swift

I have been building an app during the past month where you can upload your favorite memories. Each memory has a photo, date, short description, and place where it developed.
So the user was able to add memories, I did the following function for the photo part:
private func agregarRecuerdoFirebase() {
guard let imagenSeleccionada = self.imagen else {
print("No hay imagen")
return
}
guard let imagenData = imagenSeleccionada.jpegData(compressionQuality: 0.4) else {
return
}
let storageRef = Storage.storage().reference(forURL: "gs://chinahub-68043.appspot.com")
let storageRecuerdos = storageRef.child("recuerdos").child("recuerdoss")
let metadata = StorageMetadata()
metadata.contentType = "image/png"
storageRecuerdos.putData(imagenData, metadata: metadata) { (storageMetaData, error) in
if error != nil {
print(error?.localizedDescription)
return
}
}
Everything is working fine except the uploading to Firebase Storage. After uploading one photo to the storage, when I want to upload a second one it won't let me. Instead, the second image will replace the first one. How could I create a unique ID every time I want to add a new memory so that I could store it under that ID into the Storage?? Or is there another way for being able to achieve what I want??

try to replace below line in your project
let storageRecuerdos = storageRef.child("recuerdos").child("recuerdoss\(UUID().uuidString)\(Date().timeIntervalSince1970)")

Related

user does not have permission to access gs:// xxx.appspot.com

In this application I created authencation, database with firebase. but in my post, which consists of title, content, and image, I only see my default image. I'm having a bit of a problem with storage in the database, first uploading the image to firebase storage and then taking its url.
import Foundation
import SwiftUI
import Firebase
import FirebaseStorage
class StorageStore: ObservableObject {
let storageRef = Storage.storage().reference()
func uploadImage(_ image: UIImage, completion: #escaping (URL?) -> Void) {
let imageRef = storageRef.child("images/"+timeString()+".jpg")
guard let imageData = image.jpegData(compressionQuality: 0.1) else {
return completion(nil)
}
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
imageRef.putData(imageData, metadata: metadata, completion: { [self] (metadata, error) in
if let error = error {
assertionFailure(error.localizedDescription) // 🛑
//Thread 1: Fatal error: User does not have permission to access gs://ios-post-193ec.appspot.com/images/2022-03-29T10:03:18Z.jpg.
return completion(nil)
}
imageRef.downloadURL(completion: { (url, error) in
if let error = error {
assertionFailure(error.localizedDescription)
return completion(nil)
}
completion(url)
})
})
}
func timeString() -> String {
let now = Date()
let formatter = ISO8601DateFormatter()
let datetime = formatter.string(from: now)
print(datetime)
return datetime
}
}
as a result, I can't upload the image to storage
In this case, I have an error (🛑) as shown above. instead of the default image, one of the 6 permanent images that would be in the simulator had to come out.
The error message shows that the user does not have permission to access the file. So it looks like you have security rules controlling who can access the files in your Cloud Storage through Firebase, and those rules reject this read operation. I recommend checking the documentation I linked (there's also an old, but still great, video in there) to learn how to allow the operation, while still keeping the files secure.

Using Firebase Storage for Uploading Images

I can only upload a single photo to FirebaseStorage.
All the tutorials I have seen on youtube use FirebaseStorage to save user's profile pictures. However, I am trying to make a restaurant app where I should be able to keep several pictures and not only one. My code right now only allows me to keep one. As soon as I try to upload a second image, it erases the first one.
Here's my code:
#IBAction func agregarComidaFav(_ sender: Any) {
guard let imageData = imagen?.jpegData(compressionQuality: 0.4) else {
return
}
let storageRef = Storage.storage().reference(forURL: "gs://comidas-68043.appspot.com")
let storageProfileRef = storageRef.child("ComidasFavoritas")
let metadata = StorageMetadata()
metadata.contentType = "image/png"
storageRef.child("comidasFavoritas/png").putData(imageData, metadata: metadata) { (storageMetaData, error) in
if error != nil {
print(error?.localizedDescription ?? "")
return
}
}
storageProfileRef.downloadURL(completion: { (url, error) in
if let metaImageUrl = url?.absoluteString {
print(metaImageUrl)
self.imagenURL = metaImageUrl
}
})
var ref: DocumentReference? = nil
ref = db.collection("comidasFavoritas").addDocument(data: [
"imagenURL" : imagenURL
]) { err in
if let err = err {
print("Error agregando comida: \(err)")
} else {
let id = ref!.documentID
print("Comida agregado con ID: \(id)")
}
}
}
This line:
storageRef.child("comidasFavoritas/png").putData(...)
...guarantees that each time, the data is going to be written to "comidasFavoritas/png"
I don't know anything about how you're keeping track of your data/images in your app, but you'll probably need some way to keep track of an ID for that image. Then, when you store it, you could store it like:
storageRef.child("comidasFavoritas/png\(imageId)").putData(...)
You'd probably also want to store that ID in your database when you store the image URL.

Swift : My files in Firebase Storage wouldn't be deleted

I've got an application which allow user to save some picture on firebase Storage.
I'm trying to allow user to delete this files from the app, and so also to delete it from the storage.
My code :
if let user = Auth.auth().currentUser{
// user is connect
let storRef = Storage.storage().reference()
let userID = Auth.auth().currentUser?.uid
storRef.child("Planes").child(userID!).child(dataME[indexPath.row].image).delete(completion: nil)
self.tableView.reloadData()
dataME.remove(at: indexPath.row)
}else{
fatalError("⛔️ error ...")
}
Now in this case the line in my tableView is totally deleted with the other part of my code the database references is also deleted but the storage doesn't erase the picture ... Why ?
Thank's a lot for your help
Check if you get error when you delete storage
let storageRef = Storage.storage().reference().child("Planes").child(userID!).child(dataME[indexPath.row].image)
storageRef.delete { (error) in
if error != nil{
print(error)
return
}
// else proceed
}
You should not search by image.
Instead try using download URL that firebase supply
you can get the URL from the firebase dashboard by clicking on storage and than clicking on the current image, there you can see the download image.
when you upload an image it returns callback with URL, you have to save the URL on your data structure
upload image example:
func uploadImagePic(img1 :UIImage){
var data = NSData()
data = UIImageJPEGRepresentation(img1!, 0.8)! as NSData
// set upload path
let filePath = "\(userid)" // path where you wanted to store img in storage
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
self.storageRef = FIRStorage.storage().reference()
self.storageRef.child(filePath).put(data as Data, metadata: metaData){(metaData,error) in
if let error = error {
print(error.localizedDescription)
return
}else{
//store downloadURL
let downloadURL = metaData!.downloadURL()!.absoluteString
data[index].downloadURL = downloadURL
}
}
}
// delete example
let storage = Storage.storage()
let url = data[index].downloadURL
let storageRef = storage.reference(forURL: url)
storageRef.delete { error in
if let error = error {
print(error)
} else {
// File deleted successfully
}
}

How to update a storage node firebase swift

I want the FB Storage node under the user's uid (which has only one datafile) to be updated with the new file data. Using .putData just adds another file into the node, and I'm not sure how to use the .update call as it uses metadata and I only know how to create uploadData.
#objc func doneTapped() {
guard let uid = Auth.auth().currentUser?.uid else {return}
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child(uid)
let storageFileRef = storageRef.child(filename)
guard let image = self.profileImageView.image else {return}
guard let uploadData = UIImageJPEGRepresentation(image, 0.3) else {return}
storageFileRef.putData(uploadData, metadata: nil) { (metadata, error) in
if error != nil {
print ("Couldn't upload new profile pic:", error as Any)
return
}
Actually I fixed the issue, by just removing the filename. So in the previous case I was creating a uid folder and in that folder would be a list of images, but since I just want to store just one image, I made that user uid the actual filename, not the name of the folder to hold files.
let storageFileRef = Storage.storage().reference().child("profile_images").child(uid)
Basically just shaved off the .child(filename) piece of the reference

Firebase multiple file uploading issue with Swift 3

So I am fairly new to swift and firebase, however I have come to realize that using firebase to sync data has created a particular issue for me. I have a very simple application that basically allows users to upload multiple images onto the firebase storage.
What is happening in my code now is that once the very first image that was uploaded is done, the view segues to the next view controller. What I want to do is to only have it segue when ALL of the images are uploaded not just one
What I have attempted to do is create a List of Floats and for every Image that the user intends to upload, I will only keep track of the very last Image uploaded. However, I have to believe that there is another way of doing this. Furthermore my solution does not seem to be working correctly.
func observeUploadProgress(for job: Job) {
let imageName = UUID().uuidString
let storageRef = FIRStorage.storage().reference().child("\(imageName).png")
let uploadData = UIImagePNGRepresentation(job.beforeImage!)
let uploadTask = storageRef.put(uploadData!, metadata: nil, completion: { (metadata, error) in
if error != nil {
print(error)
return
}
job.beforeImageUrl = (metadata?.downloadURL()?.absoluteString)!
self.uploadingImagesToFirebase = false
if (self.arrayProgressList[self.arrayProgressList.count - 1] >= 1.0) {
self.alertController?.dismiss(animated: true, completion: nil)
self.performSegue(withIdentifier: "unwindFromCustomerDetailsSegue", sender: self)
}
})
self.arrayProgressList.append(0.0)
let curr_index = self.arrayProgressList.count - 1
uploadTask.observe(.progress) { (snapshot) in
guard let progress = snapshot.progress else { return }
self.uploadingImagesToFirebase = true
self.arrayProgressList[curr_index] = Float(progress.fractionCompleted)
self.progressView?.progress = self.arrayProgressList[self.arrayProgressList.count - 1]
}
}