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.
Related
I'm trying to make a simple Instagram Clone App to learn more about Firebase. So far I can share Images, Comments, Likes, but when it comes to videos, the app fails to do that. I mange to upload the Videofile to the Storage, but I don't get the videoUrl to the Database. I'm grateful for suggestions.
class ShareService {
static var REF_STORAGE_POST = Storage.storage().reference().child("posts")
static func uploadDataToStorage(imageData: Data, videoUrl: URL? = nil, postText: String, imageRatio: CGFloat, onSuccess: #escaping () -> Void ) {
// 1. upload Video
if let _videoUrl = videoUrl {
self.uploadVideoToFireBaseStorage(videoUrl: _videoUrl, onSucces: { (videoUrlString) in
self.uploadImageToFireBaseStorage(data: imageData, onSucces: { (thumbnailUrlString) in
self.uploadDataToDatabase(imageUrl: thumbnailUrlString, videoUrl: videoUrlString, postText: postText, imageRatio: imageRatio, onSuccess: onSuccess)
})
})
} else {
// 2. upload image
self.uploadImageToFireBaseStorage(data: imageData, onSucces: { (imageUrlString) in
self.uploadDataToDatabase(imageUrl: imageUrlString, postText: postText, imageRatio: imageRatio, onSuccess: onSuccess)
})
}
}
fileprivate static func uploadVideoToFireBaseStorage(videoUrl: URL, onSucces: #escaping (_ videoUrl: String) -> Void) {
let videoIdString = NSUUID().uuidString
let storageRef = REF_STORAGE_POST.child(videoIdString)
print(videoUrl)
let metadata = StorageMetadata()
//specify MIME type
metadata.contentType = "video/quicktime"
if let videoUrl = NSData(contentsOf: videoUrl) as Data? {
storageRef.putData(videoUrl, metadata: metadata) { (metaData, error) in
if error != nil {
print("upload video error")
}
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil {
print(error!.localizedDescription)
return
}
let videoUrlString = url?.absoluteString
onSucces(videoUrlString ?? "no video")
})
}
}
// upload image
fileprivate static func uploadImageToFireBaseStorage(data: Data, onSucces: #escaping (_ imageUrl: String) -> Void) {
let photoIdString = NSUUID().uuidString
let storageRef = REF_STORAGE_POST.child(photoIdString)
storageRef.putData(data, metadata: nil) { (metaData, error) in
if error != nil {
print("upload image error")
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil {
print(error!.localizedDescription)
return
}
let imageUrlString = url?.absoluteString
onSucces(imageUrlString ?? "no image")
})
}
}
fileprivate static func uploadDataToDatabase(imageUrl: String, videoUrl: String? = nil, postText: String, imageRatio: CGFloat, onSuccess: #escaping () -> Void) {
let newPostId = PostApi.shared.REF_POSTS.childByAutoId().key
let newPostRef = PostApi.shared.REF_POSTS.child(newPostId!)
let postTime = Date().timeIntervalSince1970
print(postTime)
guard let currentUserUid = UserApi.shared.CURRENT_USER_UID else { return }
var dic = ["uid" : currentUserUid, "imageUrl" : imageUrl, "imageRatio" : imageRatio, "postText" : postText] as [String : Any]
if let _videoUrl = videoUrl {
dic["videoUrl"] = _videoUrl
}
newPostRef.setValue(dic) { (error, _) in
if error != nil {
print(error?.localizedDescription as Any)
}
// Show posts in newsfeed
FeedApi.shared.REF_NEWSFEED.child(currentUserUid).child(newPostId!).setValue(true)
// Eigene Posts markieren
PostApi.shared.REF_MY_POSTS.child(currentUserUid).child(newPostId!).setValue(true)
print("Post created")
onSuccess()
}
}
}
I want to pick video from Images Picker then I want to send video in firebase and retrieve it Please provide code in swift 5, i write code also for sending video on firebase
func downloadImages(folderPath:String,success:#escaping (_ image:UIImage)->(),failure:#escaping (_ error:Error)->()){
// Create a reference with an initial file path and name
let reference = Storage.storage().reference(withPath: "\(folderPath)")
reference.getData(maxSize: (1 * 1024 * 1024 * 1024 * 1024 * 1024)) { (data, error) in
if let _error = error{
print(_error)
failure(_error)
} else {
if let _data = data {
let myImage:UIImage! = UIImage(data: _data)
success(myImage)
}
}
}
}
Upload video On firebase Storage is
func upload(file: URL, completion: #escaping ((_ url : URL?) -> ())) {
let name = "\(Int(Date().timeIntervalSince1970)).mp4"
do {
let data = try Data(contentsOf: file)
let storageRef =
Storage.storage().reference().child("Videos").child(name)
if let uploadData = data as Data? {
let metaData = StorageMetadata()
metaData.contentType = "video/mp4"
storageRef.putData(uploadData, metadata: metaData
, completion: { (metadata, error) in
if let error = error {
completion(nil)
}
else{
storageRef.downloadURL { (url, error) in
guard let downloadURL = url else {
completion(nil)
return
}
completion(downloadURL)
}
print("success")
}
})
}
}catch let error {
print(error.localizedDescription)
}
}
and Get Video From firebase
let reference = Storage.storage().reference().child("Videos").child(folderPath)
reference.getData(maxSize: INT64_MAX) { (data, error) in
if let error = error {
print("Error downloading image data: \(error)")
return
}
reference.getMetadata(completion: { (metadata, metadataErr) in
if let error = metadataErr {
print("Error downloading metadata: \(error)")
return
}
else {
reference.downloadURL { URL, error in
completion(URL)
print(URL)
}
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")")
}
}
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)
func uploadImage(){
let storage = Storage.storage()
let storageRef = storage.reference()
let uploadData = self.imageView.image!.jpegData(compressionQuality: 0.75)
let imagesRef = storageRef.child("images/myImage.jpg") //not sure how is it done
let uploadTask = imagesRef.putData(uploadData!, metadata: nil) { (metadata, error) in
guard let metadata = metadata else {
return
}
let size = metadata.size
imagesRef.downloadURL { (url, error) in
guard let downloadURL = url else {
return
}
}
}
}
func retrieveData(){
let userID = Auth.auth().currentUser?.uid
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
let userData = snapshot.value as? NSDictionary
print("Welcome back,", userData?["username"])
}) { (error) in
print(error.localizedDescription)
}
}
Hi, I'm looking for a way for user to upload image onto firebase based on their user id. Can anyone suggest how this can be achieved? Thanks in advance.
You can do something like this:
func sendMessageWithProperties(properties: [String: Any]) {
let ref = Database.database().reference().child("messages")
let childRef = ref.childByAutoId()
let toId = self.user?.id
let fromId = Auth.auth().currentUser?.uid
let timestamp: Int = Int(NSDate().timeIntervalSince1970)
var values: [String: Any] = ["toId": toId!,
"fromId": fromId!,
"timestamp": timestamp]
// To append other properties into values
properties.forEach({values[$0] = $1})
childRef.updateChildValues(values) { (error, ref) in
if error != nil {
print(error!)
return
}
let userMessageRef = Database.database().reference().child("user-messages").child(fromId!).child(toId!)
let messageId = childRef.key
userMessageRef.updateChildValues([messageId: 1])
let receiverMessageRef = Database.database().reference().child("user-messages").child(toId!).child(fromId!)
receiverMessageRef.updateChildValues([messageId: 1])
}
}