Uploading multiple files to Firebase Storage Very Slow - ios

I am trying to upload two files to firebase storage at the same time. From what I understand this is not possible so what I did was try to upload one first and then the next file once the first is done.
It is working now, however the upload speed is very slow. Is this because of an issue with my code or is it because Im waiting for two uploads as opposed to one.
var index = 0
var urls = [String]()
fileprivate func uploadToServer(data: Any) {
if index == 0 {
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("posts").child(filename)
storageRef.putData(data as! Data, metadata: nil) { (metadata, err) in
if let err = err {
self.navigationItem.rightBarButtonItem?.isEnabled = true
print("Failed to upload post image:", err)
self.showHUDwithError(error: err)
return
}
storageRef.downloadURL(completion: { (downloadURL, err) in
if let err = err {
print("Failed to fetch downloadURL:", err)
self.showHUDwithError(error: err)
return
}
guard let thisUrl = downloadURL?.absoluteString else { return }
self.urls.append(thisUrl)
self.index = self.index + 1
if self.type == "image" {
// we are done then so do the save to server call here
self.saveToDatabaseWithImageUrl()
} else {
self.uploadToServer(data: self.videoUrl as Any)
}
})
}
return
}
if index == 1 {
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("posts").child(filename)
storageRef.putFile(from: data as! URL, metadata: nil) { (metadata, err) in
if let err = err {
self.navigationItem.rightBarButtonItem?.isEnabled = true
print("Failed to upload post image:", err)
self.showHUDwithError(error: err)
return
}
storageRef.downloadURL(completion: { (downloadURL, err) in
if let err = err {
print("Failed to fetch downloadURL:", err)
self.showHUDwithError(error: err)
return
}
guard let thisUrl = downloadURL?.absoluteString else { return }
self.urls.append(thisUrl)
self.saveToDatabaseWithImageUrl()
self.index = 0
})
}
}
}

Related

how to read the url string of uploaded image in a view?

this is the upload image function is inside the view
private func persistImageToStorage() {
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Storage.storage().reference(withPath: uid)
guard let imageData = self.image?.jpegData(compressionQuality: 0.5) else { return }
ref.putData(imageData, metadata: nil) { metadata, err in
if let err = err {
self.loginStatusMessage = "Failed to push image to Storage: \(err)"
return
}
ref.downloadURL { url, err in
if let err = err {
self.loginStatusMessage = "Failed to retrieve downloadURL: \(err)"
return
}
self.loginStatusMessage = "Successfully stored image with url: \(url?.absoluteString ?? "")"
print(url?.absoluteString as Any)
}
}
}
i want to read the url?.absoluteString in its view and all the functions within the view ? how can i extract that url?.absoluteString to be read ?
if you could kindly show me the way, thank you alot

Can not upload PDF file to Firebase Storage

I need to upload a PDF file to Firebase Storage, and I works with my Simulator. But when I test on a real device, I get an infinite loading loop...
I searched for solutions, and read that I have to putData instead of putFile, and add a metadata.contentType.
I followed these 2 steps, but unfortunately it still does not work on a real device...
Here's my function:
func uploadDocs(docsArray : [URL], completionHandler: #escaping ([String]) -> ()){
var uploadedDocsUrlsArray = [String]()
var uploadCount = 0
let docsCount = docsArray.count
for doc in docsArray{
let docName = UUID().uuidString
let storageRef = Storage.storage().reference().child("documents").child(docName)
let metadata = StorageMetadata()
metadata.contentType = "application/pdf"
if let data = NSData(contentsOf: doc) as Data? {
storageRef.putData(data, metadata: metadata) { (_, err) in
if err != nil {
print(err!.localizedDescription)
return
}
storageRef.downloadURL { (url, err) in
if err != nil {
print("Failed to download url:", err!)
return
} else {
uploadedDocsUrlsArray.append(url?.absoluteString ?? "")
uploadCount += 1
print("Number of documents successfully uploaded: \(uploadCount)")
if uploadCount == docsCount{
print("All documents are uploaded successfully")
completionHandler(uploadedDocsUrlsArray)
}
}
}
}
}
}
}

Not able to get the url of uploaded image on firebase storage

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")")
}
}

How to upload an array of images in Firebase Storage using iOS Swift

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)

Firebase image upload with swift

When i run code, completion handler block does not working.When line work mediaFolder.child(userId!).putData(data, metadata: nil) { (metadata, error) in image file upload in storage but code does not running in block. This is my code :
if let data = self.profileImage.image?.jpegData(compressionQuality: 0.5)
{
mediaFolder.child(userId!).putData(data, metadata: nil) { (metadata, error) in
if error != nil {
// errror
}
else {
//enter code here
}
}
Please see below code to upload image data to Storage and get the download url
var imgData: NSData = NSData(data: UIImageJPEGRepresentation((self.img_Photo?.image)!, 0.5)!)
self.uploadProfileImageToFirebase(data: imgData)
func uploadProfileImageToFirebase(data:NSData){
let randomPic = parentVC?.randomString(length: 10)
let storageRef = Storage.storage().reference().child("Profile_Pics").child("\(userId ?? randomPic).jpg")
if data != nil {
storageRef.putData(data as Data, metadata: nil, completion: { (metadata, error) in
if(error != nil){
print(error)
return
}
guard let userID = Auth.auth().currentUser?.uid else {
return
}
// Fetch the download URL
storageRef.downloadURL { url, error in
if let error = error {
// Handle any errors
if(error != nil){
print(error)
return
}
} else {
// Get the download URL for 'images/stars.jpg'
let urlStr:String = (url?.absoluteString) ?? ""
print(urlStr)
}
}
})
}

Resources