简体   繁体   中英

Uploading an Image with Firebase & Swift (iOS)

Before I start, I would just like to pre-warn that my code is most likely not correct due to me being a beginner at coding with Swift.

I am creating an app for a university project, it is the first large app that I have created and I haven't been coding for very long.

I am having a problem when trying to upload an image whilst creating an account with firebase, I have had the code working previously but I was writing to the database with 'childByAutoId()' which was working fine, however I realised that I needed to be writing to the database and saving it by the users ID instead. After I changed 'childByAutoId()' to 'child(uid)' which is my prefixed variable for the users ID it stopped uploading the images and I can't figure out why. I have tried to go back to when it was working with childByAutoId() but now that isn't working either.

My code:

import UIKit
import Firebase
import FirebaseStorage

class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

@IBOutlet weak var profileImage: UIImageView!
@IBOutlet weak var usernameField: UITextField!
@IBOutlet weak var emailField: UITextField!
@IBOutlet weak var passwordField: UITextField!
@IBOutlet weak var dobField: UITextField!
@IBOutlet weak var selectImageButton: UIButton!

var imageFileName = ""

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))

    let datePicker = UIDatePicker()
    datePicker.datePickerMode = UIDatePickerMode.date
    datePicker.addTarget(self, action: #selector(RegisterViewController.datePickerValueChanged(sender:)), for: UIControlEvents.valueChanged)
    dobField.inputView = datePicker

    self.profileImage.layer.cornerRadius = self.profileImage.frame.size.width / 2;
    self.profileImage.clipsToBounds = true;

}

@objc func datePickerValueChanged(sender: UIDatePicker) {
    let formatter = DateFormatter()
    formatter.dateStyle = DateFormatter.Style.medium
    formatter.timeStyle = DateFormatter.Style.none
    dobField.text = formatter.string(from: sender.date)
}


@IBAction func selectImageTapped(_ sender: UIButton) {
    let picker = UIImagePickerController()
    picker.delegate = self
    self.present(picker, animated: true, completion: nil)
}

func uploadImage(image: UIImage) {
    let randomName = randomStringWithLength(length: 10)
    let imageData = UIImageJPEGRepresentation(image, 1.0)
    let uploadRef = Storage.storage().reference().child("images/profimg/\(randomName).jpg")
    let uploadTask = uploadRef.putData(imageData!, metadata: nil) { metadata,
        error in
        if error == nil {
            //success
            print("success")
            self.imageFileName = "\(randomName as String).jpg"
        } else {
            //error
            print("error uploading image")
        }
    }
}

func randomStringWithLength(length: Int) -> NSString {
    let characters: NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let randomString: NSMutableString = NSMutableString(capacity: length)

    for i in 0..<length {
        var len = UInt32(characters.length)
        var rand = arc4random_uniform(len)
        randomString.appendFormat("%C", characters.character(at: Int(rand)))
    }
    return randomString
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    // will run if the user hits cancel
    picker.dismiss(animated: true, completion: nil)
}

@objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    // will run when the user finishes picking an image from the library
    if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
        self.profileImage.image = pickedImage
        self.selectImageButton.isEnabled = false
        self.selectImageButton.isHidden = true
        uploadImage(image: pickedImage)
        picker.dismiss(animated: true, completion: nil)
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func registerTapped(_ sender: UIButton) {

    let username = usernameField.text
    let email = emailField.text
    let password = passwordField.text
    let dob = dobField.text

    Auth.auth().createUser(withEmail: email!, password: password!) { (user, error) in
        if error != nil {
            //error creating account
            let alert = UIAlertController(title: "Error", message: "An error occurred when creating your account, please try again.", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }else {
            //account created

            if (self.imageFileName != "") {
                if let uid = Auth.auth().currentUser?.uid {

                    let regObject: Dictionary<String, Any> = [
                        "uid" : uid,
                        "username" : username,
                        "dateofbirth" : dob,
                        "profimage" : self.imageFileName
                    ]
                Database.database().reference().child("posts").child(uid).setValue(regObject)

                    let vc = self.storyboard?.instantiateViewController(withIdentifier: "LoggedInVC")
                    self.present(vc!, animated: true, completion: nil)
                }else {
                    //image hasnt finished uploading
                    let alert = UIAlertController(title: "Please wait", message: "Your image has not finished uploading yet, please wait...", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                    self.present(alert, animated: true, completion: nil)
                }
            }

            //let alert = UIAlertController(title: "Success!", message: "Account has been created...", preferredStyle: .alert)
            //alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            //self.present(alert, animated: true, completion: nil)

        }
    }
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

If any of you can point me in the right direction or be able to show me where I have gone wrong within my code that would be great. I am not expected a direct solution to my problem so anything will help.

Thank you!

To upload img on firebase storage

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

            }
        }

    }

In order to get the download url from the uploaded file, based on the answer, downloadURL from metaData is now deprecated, so this is the proper way:

 storageRef.downloadURL(completion: { (url: URL?, error: Error?) in
    print(url?.absoluteString) // <- Your url
 })

You should get the download url from the reference that you just created, where you can find the downloadURL with a completion handler.

This is an updated Swift 5 answer:

func uploadImagePic(image: UIImage, name: String, filePath: String) {
    guard let imageData: Data = image.jpegData(compressionQuality: 0.1) else {
        return
    }

    let metaDataConfig = StorageMetadata()
    metaDataConfig.contentType = "image/jpg"

    let storageRef = Storage.storage().reference(withPath: filePath)

    storageRef.putData(imageData, metadata: metaDataConfig){ (metaData, error) in
        if let error = error {
            print(error.localizedDescription)

            return
        }

        storageRef.downloadURL(completion: { (url: URL?, error: Error?) in
            print(url?.absoluteString) // <- Download URL
        })
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM