使用 Firebase 上传图片 & Swift (iOS)
Uploading an Image with Firebase & Swift (iOS)
在我开始之前,我想预先警告我的代码很可能不正确,因为我是使用 Swift 编码的初学者。
我正在为大学项目创建一个应用程序,这是我创建的第一个大型应用程序,而且我编写代码的时间并不长。
我在使用 firebase 创建帐户时尝试上传图片时遇到问题,我之前的代码可以正常工作,但我使用 'childByAutoId()' 写入数据库时工作正常,但是我意识到我需要写入数据库并通过用户 ID 保存它。在我将 'childByAutoId()' 更改为 'child(uid)' 这是我的用户 ID 前缀变量后,它停止上传图像,我不明白为什么。我试图回到它使用 childByAutoId() 时的状态,但现在它也不起作用了。
我的代码:
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.
}
*/
}
如果你们中的任何人能指出我正确的方向或能够告诉我我的代码中哪里出了问题,那就太好了。我不需要直接解决我的问题,所以任何事情都会有所帮助。
谢谢!
将图片上传到 firebase 存储
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
}
}
}
为了从上传的文件中下载 url,根据答案,downloadURL
from metaData is now deprecated,所以这是正确的方法:
storageRef.downloadURL(completion: { (url: URL?, error: Error?) in
print(url?.absoluteString) // <- Your url
})
您应该从刚刚创建的引用中下载 url,您可以在其中找到带有完成处理程序的 downloadURL
。
这是更新后的 Swift 5 个答案:
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
})
}
}
在我开始之前,我想预先警告我的代码很可能不正确,因为我是使用 Swift 编码的初学者。
我正在为大学项目创建一个应用程序,这是我创建的第一个大型应用程序,而且我编写代码的时间并不长。
我在使用 firebase 创建帐户时尝试上传图片时遇到问题,我之前的代码可以正常工作,但我使用 'childByAutoId()' 写入数据库时工作正常,但是我意识到我需要写入数据库并通过用户 ID 保存它。在我将 'childByAutoId()' 更改为 'child(uid)' 这是我的用户 ID 前缀变量后,它停止上传图像,我不明白为什么。我试图回到它使用 childByAutoId() 时的状态,但现在它也不起作用了。
我的代码:
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.
}
*/
}
如果你们中的任何人能指出我正确的方向或能够告诉我我的代码中哪里出了问题,那就太好了。我不需要直接解决我的问题,所以任何事情都会有所帮助。
谢谢!
将图片上传到 firebase 存储
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
}
}
}
为了从上传的文件中下载 url,根据答案,downloadURL
from metaData is now deprecated,所以这是正确的方法:
storageRef.downloadURL(completion: { (url: URL?, error: Error?) in
print(url?.absoluteString) // <- Your url
})
您应该从刚刚创建的引用中下载 url,您可以在其中找到带有完成处理程序的 downloadURL
。
这是更新后的 Swift 5 个答案:
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
})
}
}