Having errors after updating Firebase pods. <downloadURL> <storageRef> - ios

Upgraded my Firebase pods and got a ton of errors. I used the Docs on the Firebase Docs webpage so I was able to fix most of them. Any help is much appreciated. Thanks
Errors:
Value of type 'StorageMetadata' has no member 'downloadURL'
Value of type 'StorageReference' has no member 'put'
Full Code:
import Foundation
import FirebaseStorage
class HelperService {
static func uploadDataToServer(data: Data, videoUrl: URL? = nil, ratio: CGFloat, caption: String, onSuccess: #escaping () -> Void) {
if let videoUrl = videoUrl {
self.uploadVideoToFirebaseStorage(videoUrl: videoUrl, onSuccess: { (videoUrl) in
uploadImageToFirebaseStorage(data: data, onSuccess: { (thumbnailImageUrl) in
sendDataToDatabase(photoUrl: thumbnailImageUrl, videoUrl: videoUrl, ratio: ratio, caption: caption, onSuccess: onSuccess)
})
})
//self.senddatatodatabase
} else {
uploadImageToFirebaseStorage(data: data) { (photoUrl) in
self.sendDataToDatabase(photoUrl: photoUrl, ratio: ratio, caption: caption, onSuccess: onSuccess)
}
}
}
static func uploadVideoToFirebaseStorage(videoUrl: URL, onSuccess: #escaping (_ videoUrl: String) -> Void) {
let videoIdString = NSUUID().uuidString
let storageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOF_REF).child("posts").child(videoIdString)
storageRef.putFile(from: videoUrl, metadata: nil) { (metadata, error) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
Error 1. > if let videoUrl = metadata?.downloadURL()?.absoluteString {
onSuccess(videoUrl)
}
}
}
static func uploadImageToFirebaseStorage(data: Data, onSuccess: #escaping (_ imageUrl: String) -> Void) {
let photoIdString = NSUUID().uuidString
let storageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOF_REF).child("posts").child(photoIdString)
Error 2. > storageRef.put(data, metadata: nil) { (metadata, error) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
if let photoUrl = metadata?.downloadURL()?.absoluteString {
onSuccess(photoUrl)
}
}
}
static func sendDataToDatabase(photoUrl: String, videoUrl: String? = nil, ratio: CGFloat, caption: String, onSuccess: #escaping () -> Void) {
let newPostId = Api.Post.REF_POSTS.childByAutoId().key
let newPostReference = Api.Post.REF_POSTS.child(newPostId)
guard let currentUser = Api.User.CURRENT_USER else {
return
}
let words = caption.components(separatedBy: CharacterSet.whitespacesAndNewlines)
for var word in words {
if word.hasPrefix("#") {
word = word.trimmingCharacters(in: CharacterSet.punctuationCharacters)
word = word.trimmingCharacters(in: CharacterSet.symbols)
let newHashReference = Api.HashTag.REF_HASHTAG.child(word.lowercased())
newHashReference.setValue([newPostId: true])
// let hashTagsRef = DataService.dataService.BASE_REF.child("hashTags").child(postKey)
// let data = ["to": "", "by": "\(DataService.dataService.currentUserId!)", "hashTag": word.lowercased(), "comment": self.captionTextView.text] as [String : Any]
// hashTagsRef.setValue(data)
}
}
let currentUserId = currentUser.id
var dict = ["id": currentUserId! ,"photoUrl": photoUrl, "caption": caption, "likeCount": 0, "ratio": ratio] as [String : Any]
if let videoUrl = videoUrl {
dict["videoUrl"] = videoUrl
}
newPostReference.setValue(dict, withCompletionBlock: {
(error, ref) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
Api.Feed.REF_FEED.child(Api.User.CURRENT_USER!.id!).child(newPostId).setValue(true)
let myPostRef = Api.MyPosts.REF_MYPOSTS.child(currentUserId!).child(newPostId)
myPostRef.setValue(true, withCompletionBlock: { (error, ref) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
})
ProgressHUD.showSuccess("Success")
onSuccess()
})
}
}

The ability to get a download URL from upload metadata was removed. Instead, you can use StorageReference.downloadURL()
To upload a file, you have some options, as shown in the API docs here. You can see there are variants on putData and putFile, but no put.

Related

Upload videoUrl to firebase database in switch

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

Trying to upload images into Firebase error: Value of type 'StorageMetadata' has no member 'downloadURL' - SWIFT 4

I know there have been 2 other questions like this one (linked below), and I have tried for hours trying to apply the solutions for my code but haven't been successful at it. I am trying to build my backend for my app and want to upload multiple images to Firebase as one single 'post' exactly like Instagram's feature where you do the same. The code below is my ImageUploadManager witch is intended to handle the photos being uploaded to Firebase in the 'multiple images in one post' way for my practice project.
Links to other 2 questions:
Value of type 'StorageMetadata' has no member 'downloadURL'
StorageMetadata' has no member 'downloadURL'
import UIKit
import FirebaseStorage
import Firebase
struct Constants {
struct Car {
static let imagesFolder: String = "carImages"
}
}
class ImageUploadManager: NSObject {
//Below code (comented out) is for completion progress visual
func uploadImage(_ image: UIImage, /**/ progressBlock: #escaping (_ percentage: Double) -> Void, /**/ completionBlock: #escaping (_ url: URL?, _ errorMessage: String?) -> Void) {
let storage = Storage.storage()
let storageReference = storage.reference()
//storage/carImages/{customId}/image.jpg
let imageName = "\(Date().timeIntervalSince1970).jpg"
let imagesReference = storageReference.child(Constants.Car.imagesFolder).child(imageName)
if let imageData = UIImageJPEGRepresentation(image, 0.8) {
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
let uploadTask = imagesReference.putData(imageData, metadata: metadata, completion: { (metadata, error) in
//Lines below may also be for progress bar not sure
if let metadata = metadata {
//Error here completionBlock(metadata.downloadURL(), nil)
} else {
completionBlock(nil, error?.localizedDescription)
}
//ends here
})
uploadTask.observe(.progress, handler: { (snapshot) in
//Below lines for Progress bar on upload
guard let progress = snapshot.progress else {
return
}
let percentage = (Double(progress.completedUnitCount) / Double(progress.totalUnitCount)) * 100
progressBlock(percentage)
//Ends here
})
} else {
completionBlock(nil, "Image could not be converted to Data.")
}
}
}
UPADTED CODE WITH ANSWER BELOW: Ive replaced my old 'let uploadTask = ' with his solution
import UIKit
import FirebaseStorage
import Firebase
struct Constants {
struct Car {
static let imagesFolder: String = "carImages"
}
}
class ImageUploadManager: NSObject {
//Below code (comented out) is for completion progress visual
func uploadImage(_ image: UIImage, /**/ progressBlock: #escaping (_ percentage: Double) -> Void, /**/ completionBlock: #escaping (_ url: String?, _ errorMessage: String?) -> Void) {
let storage = Storage.storage()
let storageReference = storage.reference()
//storage/carImages/{customId}/image.jpg
let imageName = "\(Date().timeIntervalSince1970).jpg"
let imagesReference = storageReference.child(Constants.Car.imagesFolder).child(imageName)
if let imageData = UIImageJPEGRepresentation(image, 0.8) {
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
// let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).png")
let uploadTask = imagesReference.putData(imageData, metadata: metadata, completion: { (metadata, error) in
if let metadata = metadata {
imagesReference.downloadURL { (url, error) in
guard let downloadURL = url else {
// Uh-oh, an error occurred!
return
}
}
completionBlock(downloadURL, nil)
} else {
completionBlock(nil, error?.localizedDescription)
}
})
uploadTask.observe(.progress, handler: { (snapshot) in
guard let progress = snapshot.progress else {
return
}
let percentage = (Double(progress.completedUnitCount) / Double(progress.totalUnitCount)) * 100
progressBlock(percentage)
})
} else {
completionBlock(nil, "Image could not be converted to Data.")
}
}
}
The download URL is no longer available on the metadata object. Instead you call download URL on the StorageReference after the upload has completed.
let uploadTask = imagesReference.putData(imageData, metadata: metadata, completion: { (metadata, error) in
if let metadata = metadata {
imagesReference.downloadURL { (url, error) in
guard let downloadURL = url else {
// Uh-oh, an error occurred!
return
}
}
completionBlock(downloadURL, nil)
} else {
completionBlock(nil, error?.localizedDescription)
}
})
Note that this is a pretty direct copy from the documentation, so I recommend studying that a bit more too: https://firebase.google.com/docs/storage/ios/upload-files#upload_from_data_in_memory

Display uploaded image using the new Firebase. swift 4

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.

I want to get the download url of image from firebase storage ios swift

I am using firebase to upload some images, and its work fine, but the problem I can not get the download url of the image
here my code
#IBAction func btnUploadImgsAction(_ sender: UIButton) {
let url1 = uploading(img: Img1)
print("///////////img 1 //////// \(url1) ////////")
let url2 = uploading(img: Img2)
print("///////////img 2 //////// \(url2) ////////")
let url3 = uploading(img: Img3)
print("///////////img 3 //////// \(url3) ////////")
let url4 = uploading(img: Img4)
print("///////////img 4 //////// \(url4) ////////")
}
func uploading( img : UIImageView)-> String{
var strURL = ""
let imageName = NSUUID().uuidString
let storeImage = self.storageRef.child("profile_Images").child(imageName)
if let uploadImageData = UIImagePNGRepresentation((img.image)!){
storeImage.putData(uploadImageData, metadata: nil, completion: { (metaData, error) in
storeImage.downloadURL(completion: { (url, error) in
if let urlText = url?.absoluteString {
strURL = urlText
print("///////////tttttttt//////// \(strURL) ////////")
}
})
})
}
return strURL
}
when I print the strURL inside the uploading method the url comes but when I printed in the btnUploadImgsAction its not coming, What am donig wrong ??
please help thanks in advance
You should create a closure method instead method which directly returns string because this method is async method
Your method declaration should be something like below
func uploading( img : UIImageView, success: (url: String) -> Void) {
// return with clouser
success(url: strurl)
}
Updated with your method
func uploading( img : UIImageView, completion: #escaping ((String) -> Void)) {
var strURL = ""
let imageName = NSUUID().uuidString
let storeImage = self.storageRef.child("profile_Images").child(imageName)
if let uploadImageData = UIImagePNGRepresentation((img.image)!){
storeImage.putData(uploadImageData, metadata: nil, completion: { (metaData, error) in
storeImage.downloadURL(completion: { (url, error) in
if let urlText = url?.absoluteString {
strURL = urlText
print("///////////tttttttt//////// \(strURL) ////////")
completion(strURL)
}
})
})
}
}
And function call would be
let str = uploading(img: imageObject) { (url) in
print(url)
}

Swift - AWS S3 Upload Image from Photo Library and download it

I've looked many amazon docs but didn't find enough information to upload and download images to S3 using Swift.
How can I do that?
After doing many research I've got this working,
import AWSS3
import AWSCore
Upload:
I assume you have implemented UIImagePickerControllerDelegate already.
Step 1:
Create variable for holding url:
var imageURL = NSURL()
Create upload completion handler obj:
var uploadCompletionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
Step 2: Get Image URL from imagePickerController(_:didFinishPickingMediaWithInfo:):
Set value of imageURL in this delegate method:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
//getting details of image
let uploadFileURL = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = uploadFileURL.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
// getting local path
let localPath = (documentDirectory as NSString).stringByAppendingPathComponent(imageName!)
//getting actual image
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let data = UIImagePNGRepresentation(image)
data!.writeToFile(localPath, atomically: true)
let imageData = NSData(contentsOfFile: localPath)!
imageURL = NSURL(fileURLWithPath: localPath)
picker.dismissViewControllerAnimated(true, completion: nil)
}
Step 3: Call this uploadImage method after imageURL set to Upload Image to your bucket:
func uploadImage(){
//defining bucket and upload file name
let S3BucketName: String = "bucketName"
let S3UploadKeyName: String = "public/testImage.jpg"
let expression = AWSS3TransferUtilityUploadExpression()
expression.uploadProgress = {(task: AWSS3TransferUtilityTask, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
dispatch_async(dispatch_get_main_queue(), {
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
print("Progress is: \(progress)")
})
}
self.uploadCompletionHandler = { (task, error) -> Void in
dispatch_async(dispatch_get_main_queue(), {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)");
}
else{
print("Sucess")
}
})
}
let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
transferUtility.uploadFile(imageURL, bucket: S3BucketName, key: S3UploadKeyName, contentType: "image/jpeg", expression: expression, completionHander: uploadCompletionHandler).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let exception = task.exception {
print("Exception: \(exception.description)")
}
if let _ = task.result {
print("Upload Starting!")
}
return nil;
}
}
Download:
func downloadImage(){
var completionHandler: AWSS3TransferUtilityDownloadCompletionHandlerBlock?
let S3BucketName: String = "bucketName"
let S3DownloadKeyName: String = "public/testImage.jpg"
let expression = AWSS3TransferUtilityDownloadExpression()
expression.downloadProgress = {(task: AWSS3TransferUtilityTask, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
dispatch_async(dispatch_get_main_queue(), {
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
print("Progress is: \(progress)")
})
}
completionHandler = { (task, location, data, error) -> Void in
dispatch_async(dispatch_get_main_queue(), {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)")
}
else{
//Set your image
var downloadedImage = UIImage(data: data!)
}
})
}
let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
transferUtility.downloadToURL(nil, bucket: S3BucketName, key: S3DownloadKeyName, expression: expression, completionHander: completionHandler).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let exception = task.exception {
print("Exception: \(exception.description)")
}
if let _ = task.result {
print("Download Starting!")
}
return nil;
}
}
Ref. for upload image
Ref. for download image
Many thanks to jzorz
If all you want is to download the image, this is a much more concise and correct way to do it:
func downloadImage(bucketName: String, fileName: String, completion: (image: UIImage?, error: NSError?) -> Void) {
let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
transferUtility.downloadDataFromBucket(bucketName, key: fileName, expression: nil) { (task, url, data, error) in
var resultImage: UIImage?
if let data = data {
resultImage = UIImage(data: data)
}
completion(image: resultImage, error: error)
}
}
func uploadFile(with resource: String, type: String) {
let key = "\(resource).\(type)"
let localImagePath = Bundle.main.path(forResource: resource, ofType: type)
let localImageUrl = URL(fileURLWithPath: localImagePath!)
let transferManager1 = AWSS3TransferUtility.default()
let expression = AWSS3TransferUtilityUploadExpression()
self.uploadCompletionHandler = { (task, error) -> Void in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)");
}
else{
print("Sucess")
}
})
}
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadFile(localImageUrl, bucket: "", key: key, contentType: "video/mov", expression: expression, completionHandler: uploadCompletionHandler).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let _ = task.result {
print("Upload Starting!")
}
return nil;
}
}
#IBAction func uplaodVideo(){
uploadFile(with: "random", type: "mov")
}
The above answers were really helpful to me, but they're quite outdated due to a lot of the nomenclature being changed. So I'm providing an updated version of the answer based on the latest Swift frameworks.
Image Picker Controller:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
//getting details of image
let uploadFileURL = info[UIImagePickerController.InfoKey.referenceURL] as! NSURL
let imageName = uploadFileURL.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String
// getting local path
let localPath = (documentDirectory as NSString).appendingPathComponent(imageName!)
//getting actual image
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let data = image.pngData()
let imageData = image.pngData()! as NSData
let photoURL = NSURL(fileURLWithPath: localPath)
self.uploadFileURL = photoURL
self.uploadImage(inputData: imageData)
do {
let result = try data?.write(to: photoURL as URL, options: .atomic)
} catch let error {
print(error)
}
picker.dismiss(animated: true, completion: nil)
}
Upload Image:
A quick note on upload image. I hashed my filenames. This is not a necessary step, but I highly recommend to do so in the production stage just to ensure no filenames conflict in your S3 bucket.
func uploadImage(inputData: NSData) {
//defining bucket and upload file name
let S3BucketName: String = "your_bucket_name"
let hashed = SHA256.hash(data: inputData)
let S3UploadKeyName: String = hashed.compactMap { String(format: "%02x", $0) }.joined()
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = {(task: AWSS3TransferUtilityTask, progress: Progress) in
print(progress.fractionCompleted)
}
self.uploadCompletionHandler = { (task, error) -> Void in
DispatchQueue.main.async(execute: {
if ((error) != nil){
print("Failed with error")
print("Error: \(error!)")
}
else{
print("Success")
}
})
}
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadFile(self.uploadFileURL! as URL, bucket: S3BucketName, key: S3UploadKeyName, contentType: "image/jpeg", expression: expression, completionHandler: uploadCompletionHandler).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let _ = task.result {
print("Upload Starting!")
// Do something with uploadTask.
}
return nil
}
}

Resources