I am trying to save user data (email, username, and profile image) in the storage section of firebase when a user signs up (uses the sign up function). So far, I am getting data in the authentication section when someone sings up, but nothing is coming through to storage. I have Auth, Firestore, Analytics, Core, Storage, and Database pods installed.
Here is my function:
func signUp() {
Auth.auth().createUser(withEmail: email, password: password) { (authData, error) in
if error != nil {
return
}
guard let userId = authData?.user.uid else { return }
let storageRoot = Storage.storage().reference(forURL: "gs://locally-v7.appspot.com")
let storageAvatar = storageRoot.child("avatar")
let storageAvatarUserId = storageAvatar.child(userId)
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
storageAvatarUserId.putData(self.imageData, metadata: metadata) { (StorageMetadata, error) in
if error != nil {
return
}
storageAvatarUserId.downloadURL { (url, error) in
if let metaImageUrl = url?.absoluteString {
if let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest() {
changeRequest.photoURL = url
changeRequest.displayName = self.username
changeRequest.commitChanges { (error) in
if error != nil {
return
}
}
}
let firestoreRoot = Firestore.firestore()
let firestoreUsers = firestoreRoot.collection("users")
let firestoreUserId = firestoreUsers.document(userId)
let userInfo = ["username": self.username, "email": self.email, "profileImageUrl": metaImageUrl]
firestoreUserId.setData(userInfo)
}
}
}
}
}
FirebaseApp.configure() is being called already in the main file.
Related
My application is logged in via anonymous authentication, I have a class on SwiftUI for uploading a user's photo from an iPhone, however, when uploading a photo to Firebase storage, I get the error:
User is not authenticated, please authenticate using Firebase
Authentication and try again.
Here's my code:
AuthViewModel.kt:
class AuthViewModel: NSObject, ObservableObject {
#Published var userID = ""
func login() {
Auth.auth().signInAnonymously { (res, err) in
if err != nil {
print(err!.localizedDescription)
return
}
print("Success = \(res!.user.uid)")
self.userID = res!.user.uid
}
}
}
UserViewModel:
func setCurrentUserImage(profileImage: UIImage) {
guard let imageData = profileImage.jpegData(compressionQuality: 0.3) else { return }
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("UserPhotos").child("\(self.currentUser)/\(filename)")
storageRef.putData(imageData, metadata: nil) { _, error in
if let error = error {
print("Upload Image error: \(error.localizedDescription)")
return
}
storageRef.downloadURL { url, _ in
guard let profileImageURL = url?.absoluteString else { return }
let docRef = self.db.collection("users").document(self.currentUser)
docRef.getDocument(source: .cache) { (snap, err) in
guard let curUser = snap else { return }
curUser.reference.updateData(["userImage" : profileImageURL])
}
}
}
}
Firebase storage security rules:
match /{allPaths=**} {
allow read, write;
}
When using an image picker to grab the image selected and place in firebase storage I want to be able to download the URL and take place of the profile image inside the app. Unfortunately, when the process reaches the URLSession in the script nothing happens. There is not an error display nor does it dispatchQueue. The app will not crash but just skip over everything. Any ideas or suggestions to a code fix?
if let profileImageUploadedData = self.profileImage.image, let uploadData = profileImage.image?.jpegData(compressionQuality: 0.1)
{
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if error != nil
{
print("Downdloading putData Error: \(error!.localizedDescription)")
return
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil
{
print("DownloadURL ERROR \(error!.localizedDescription)")
return
}
if let profileImageUrl = url?.absoluteString
{
print("Profile image uploading...")
let values = ["profileImageUrl": profileImageUrl]
let url = URL(fileURLWithPath: profileImageUrl)
URLSession.shared.dataTask(with: url) { (data, response, error) in // ERROR OCCURING NEED TO FIX
if error != nil
{
print("* URL SESSIONS ERROR: \(error!)")
return
}
DispatchQueue.main.async
{
print("Trying to register profile")
self.registerUserIntoDatabaseWithUID(uid: uid, values: values as [String : AnyObject])
self.profileImage.image = UIImage(data: data!)
print("Dispatch: \(data!)")
}
print("Profile image successfull uploaded to storage")
}
}
})
}).resume()
print("** Profile Image Data Uploaded:\(profileImageUploadedData)")
}
}
func registerUserIntoDatabaseWithUID(uid: String, values: [String: AnyObject])
{
print("Registering to database")
let dataReference = Database.database().reference(fromURL: "URL String")
let usersReference = dataReference.child("users").child(uid)
usersReference.updateChildValues(values, withCompletionBlock: { (err, reference) in
if err != nil
{
print(err!)
return
}
// self.profileImage.image = values["profileImageUrl"] as? UIImage
// self.fetchProfileImage()
self.dismiss(animated: true, completion: nil)
print("Saved user sussccessfully in database")
})
}
}
This is a big question that is actually asking for a number of different answers so let's just focus on one;
How to authenticate a user, get a url stored in Firebase Database that
references an image stored in Firebase Storage, then download that
image.
Here we go
First - authenticate a user
Auth.auth().signIn(withEmail: user, password: pw, completion: { (auth, error) in
if let x = error {
//handle an auth error
} else {
if let user = auth?.user {
let uid = user.uid
self.loadUrlFromFirebaseDatabase(withUid: uid)
}
}
})
now the user is authenticated, get the image location url from Firebase Database
func loadUrlFromFirebaseDatabase(withUid: String) {
let thisUserRef = self.ref.child("users").child(withUid)
let urlRef = thisUserRef.child("url")
urlRef.observeSingleEvent(of: .value, with: { snapshot in
if let url = snapshot.value as? String {
self.loadImageUsingUrl(url: url)
} else {
print("no image for user")
}
})
}
Now that we have the location of the image in Firebase Storage, get it
func loadImageUsingUrl(url: String) {
let storage = Storage.storage()
let imageRef = storage.reference(forURL: url)
imageRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print("error downloading \(error)")
} else {
if let image = UIImage(data: data!) {
//do something with the image
} else {
print("no image")
}
}
}
}
Here is the code that I'm using
#objc func handleSignUp() {
guard let email = emailTextField.text, email.characters.count > 0 else { return }
guard let username = usernameTextField.text, username.characters.count > 0 else { return }
guard let password = passwordTextField.text, password.characters.count > 0 else { return }
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
if let err = error {
print("Failed to create user:", err)
return
}
print("Successfully created user:", user?.user.uid)
// guard let image = self.plusPhotoButton.imageView?.image else { return }
// guard let uploadData = UIImageJPEGRepresentation(image, 0.3) else { return }
guard let uploadData = self.plusPhotoButton.imageView?.image?.jpegData(compressionQuality: 0.3) else{return}
let filename = NSUUID().uuidString
Storage.storage().reference().child("profile_images").child(filename).putData(uploadData, metadata: nil, completion: { (metadata, err) in
if let err = err {
print("Failed to upload profile image:", err)
return
}
//this code isn't correct for swift4.2
//guard let profileImageUrl = metadata?.downloadURL()?.absoluteString else { return }
func getDownloadURL(from path: String, completion: #escaping (URL?, Error?) -> Void) {
let storageReference = Storage.storage().reference(forURL: "gs://instagramfirebase-60be5.appspot.com")
let storageRef = storageReference.child(path).downloadURL(completion: completion)
}
print("Successfully uploaded profile image")//,profileImageUrl
guard let uid = user?.user.uid else { return }
let dictionaryValues = ["username": username] as [String : Any]//, "profileImageUrl": profileImageUrl
let values = [uid: dictionaryValues]
Database.database().reference().child("users").updateChildValues(values, withCompletionBlock: { (err, ref) in
if let err = err {
print("Failed to save user info into db:", err)
return
}
print("Successfully saved user info to db")
})
})
})
}
Snapshots are as followed :
I am confused about how to get the imageUrl from firebase storage and store it in firebase database in Xcode 10 swift 4.2
Please help, Thank you for your time.
You can get the download url easily by using the following code inside the closure of your image-upload:
storageRef.downloadURL(completion: { (url, error) in
if let err = error{
// error happened - implement code to handle it
print(err)
} else {
// no error happened; so just continue with your code
print(url?.absoluteString) // this is the actual download url - the absolute string
}
Please note: Don't store the downloadURL on its own as Firebase can change tokens of the downloadURL, I'd suggest to always grab a hold of the full storage path.
I hope I was able to help.
Hey guys actually i am trying two things here:- trying to create a new account and trying to open a screen like which appears after login but it is showing "email already exist error".
#IBAction func CreateAcccountButton(_ sender: AnyObject) {
guard let eventInterest = textBox.text,let email = EmailTestfield.text, let password = PasswordTestfield.text, let name = UsernameTestfield.text else {
print("Form is not valid")
return
}
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
if let error = error {
print(error)
return
}
guard let uid = user?.uid else {
return
}
//successfully authenticated user
let imageName = UUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).png")
if let uploadData = UIImagePNGRepresentation(self.Profilepicture.image!) {
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if let error = error {
print(error)
return
}
print (metadata)
// let downloadURL = metadata?.downloadURL()
// print("URL ", downloadURL)
if let Profilepictureurl = metadata?.downloadURL()?.absoluteString {
let values = ["name": name, "email": email,"EventInterest":eventInterest,"Password":password,"Profilepictureurl": Profilepictureurl ]
let user = User(dictionary: values as [String : AnyObject])
let customViewController = MessagesController()
customViewController.setupNavBarWithUser(user)
customViewController.fetchUserAndSetupNavBarTitle()
// customViewController.navigationItem.title = values["name"] as? String
self.dismiss(animated: true, completion: nil)
self.registeruserintoDb(uid,values: values as [String : AnyObject])
}
})
}
}
)
}
fileprivate func registeruserintoDb(_ uid: String, values: [String: AnyObject]) {
let ref = Database.database().reference()
let usersReference = ref.child("users").child(uid)
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err!)
return
}
})
}
It's exactly what the error says, you already have a user with that email. Instead, use the auth.signIn method and check for currently signed in users.
I am having a bit of an issue checking Firebase Storage when a user logs into my app. When a user logs in an image is created and stored successfully in Firebase database and storage, but every time a user logs out and logs back into the app the profileImage file (not the child value url string) is duplicated in Firebase Storage as a new and separate image file.
I would like the app when logging in to check the Firebase storage for the profileImage file, and if it exists then do not re-create that same image in storage. I understand the logic of checking Firebase for image and if does not exist, than create new image. I am just having some trouble with the syntax. Thanks for help in advance!
// login user with Facebook
func loginWithFacebook() {
let accessToken = FBSDKAccessToken.current()
guard let accessTokenString = accessToken?.tokenString else { return }
let credentials = FIRFacebookAuthProvider.credential(withAccessToken: accessTokenString)
FIRAuth.auth()?.signIn(with: credentials, completion: { (user, error) in
if error != nil {
print("Something went wrong with our FB user: ", error ?? "")
return
}
guard let uid = user?.uid else {
return
}
let imageName = NSUUID().uuidString
let storageRef = FIRStorage.storage().reference().child("profile_images").child("\(imageName).png")
let photoUrl = user?.photoURL
// check to see if current user already has stored image with URL
if FIRStorage.storage().reference().child("profile_images").child("\(imageName).png") == nil {
if let imageData = NSData(contentsOf: photoUrl!) {
storageRef.put(imageData as Data, metadata:nil) {
(metadata, error) in
if error != nil {
print(error!)
return
} else {
if let profileImageUrl = metadata?.downloadURL()?.absoluteString {
let values = ["name": user!.displayName!, "email": user!.email!, "profileImageUrl": profileImageUrl]
self.registerUserWithUID(uid: uid, values: values as [String : AnyObject])
}
}
}
}
} else {
print("image already exists")
}
print("Successfully logged in with our user: ", user ?? "")
self.delegate?.finishLoggingIn()
})
private func registerUserWithUID(uid: String, values: [String: AnyObject]) {
// create items in database upon creating user ---------------
let ref = FIRDatabase.database().reference()
let usersReference = ref.child("users").child(uid)
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err!)
return
}
print("user has been saved to Firebase database")
})
}
I think the issue is with the "if" condition. You are referencing the location, but not checking with the actual data in that location.
You can implement that using .observerSingleEventOf().
private func checkUser (imageName:String, _ completionHandler: #escaping(Bool) -> Void)
{
let userExists = FIRStorage.storage().reference().child("profile_images")
userExists.observeSingleEvent(of: .value, with:{(snapshot) in
if snapshot.hasChild(imageName){
print ("Image already exists")
completionHandler(false)
}
else
{
print ("Image does not exist")
print ("store the image")
}
})
}
`