I followed the tutorial from https://developers.google.com/drive/ios/quickstart
i register my app, got secret key and put it in the appication, getting some token here:
func viewController(vc : UIViewController,
finishedWithAuth authResult : GTMOAuth2Authentication, error : NSError?) {
if let error = error {
service.authorizer = nil
showAlert("Authentication Error", message: error.localizedDescription)
return
}
service.authorizer = authResult
It's fine. But when i tried to upload photo to google disc - i got this error:
{"error":{"code":403,"message":"Insufficient Permission","data":[{"domain":"global","reason":"insufficientPermissions","message":"Insufficient Permission"}]},"id":"gtl_1"}
2016-04-23 14:21:06.329 PROJECT_NAME[560:210039] Premature failure: upload-status:"final" location:(null)
Here is the code. Can someone tell me what i m doing wrong?
func uploadPhoto(image: UIImage) {
let name = "Photo"
let content = image
let mineType = "image/jpeg"
let metadata = GTLDriveFile()
metadata.name = name
guard let data = UIImagePNGRepresentation(content) else {
return
}
let uploadParameters = GTLUploadParameters(data: data, MIMEType: mineType)
let query = GTLQueryDrive.queryForFilesCreateWithObject(metadata, uploadParameters: uploadParameters) as GTLQueryDrive
service.executeQuery(query) { (ticket, updatedFile, error) in
print(ticket)
if error != nil {
print(error)
}
}
}
Related
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)
I'm trying to allow a user to upload an image along with their audio recording. Per the Firebase documentation, I nested the database reference inside of the storage reference to upload them, but I'm unable to create and send URLs for both the image and audio. I could send them separately as two different database refs but that would cause issues when downloading them back to the application (without some type of identifier linking the image and audio). If anyone knows how to send the two as one ref, your help is appreciated.
func uploadRecording () {
if let audioRecording = recordedAudioURL {
let audioIDString = NSUUID().uuidString
let audioStorageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOT_REFERENCE).child("posts").child(audioIDString)
audioStorageRef.putFile(from: audioRecording, metadata: nil, completion: {(_ , error: Error?) in
if error != nil {
print (error)
return
}
audioStorageRef.downloadURL(completion: { (url: URL?, error: Error?) in
if let audioDownloadURL = url?.absoluteString {
if error != nil {
print(error)
return
}
sendDatatoDatabase(recordedAudioURL: audioDownloadURL)
}
})
})
}
// upload selected image to Firebase
func uploadImage () {
if let lessonImg = self.selectedImage, let imageData = lessonImg.jpegData(compressionQuality: 0.1) {
let photoIDString = NSUUID().uuidString
let photoStorageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOT_REFERENCE).child("posts").child(photoIDString)
photoStorageRef.putData(imageData, metadata: nil, completion: {(_ , error: Error?) in
if error != nil {
print(error)
return
}
photoStorageRef.downloadURL(completion: { (url: URL?, error: Error?) in
if let photoDownloadURL = url?.absoluteString {
if error != nil {
print(error)
return
}
}
})
}
)}
}
For the newPostReference I receive an error : Use of unresolved identifier 'photoDownloadURL'
func sendDatatoDatabase (recordedAudioURL: String) {
let ref = Database.database().reference()
let postsReference = ref.child("posts")
let newPostID = postsReference.childByAutoId().key
let newPostReference = postsReference.child(newPostID!)
newPostReference.setValue(["recordingURL": recordedAudioURL, "photoURL": photoDownloadURL, "lessonTitle": lessonTitleTextField.text!, "lessonTopic": lessonTopicTextField.text!, "lessonLocation": lessonlocationTextField.text!])
self.lessonlocationTextField.text = " "
self.lessonTopicTextField.text = " "
self.lessonTitleTextField.text = " "
self.tabBarController?.selectedIndex = 1
}
I am trying to make a Sign in / Sign up screen with Firebase. And i created a swift class for send data to Firebase and i called the class "DataService". I have also Sign in and Sign up classes. In the "DataService" class i cant create more than one function, i am getting error like Value of type DataService has no member "Sign up" when i am trying to create a sign up function. But the other function works fine. I can have just only one function in this class(DataService).
DATASERVICE class
import Foundation
import Firebase
import FirebaseAuth
import FirebaseStorage
let rootRef = FIRDatabase.database().reference()
class DataService {
static let dataService = DataService()
private var _BASE_REF = rootRef
private var _PHOTO_REF = rootRef.child("photos")
var BASE_REF: FIRDatabaseReference {
return _BASE_REF
}
var PHOTO_REF: FIRDatabaseReference {
return _PHOTO_REF
}
var storageRef: FIRStorageReference{
return FIRStorage.storage().reference()
}
var fileUrl: String!
// Share Photo Data
func shareNewPhoto(user: FIRUser, caption: String, data: NSData) {
let filePath = "\(user.uid)/\ (Int(NSDate.timeIntervalSinceReferenceDate))"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
storageRef.child(filePath).put(data as Data, metadata: metaData) { (metadata, error) in
if let error = error {
print("Error uploading: /\(error.localizedDescription)")
}
// Create a Url for data ( Story Photo)
self.fileUrl = metadata!.downloadURLs![0].absoluteString
if let user = FIRAuth.auth()?.currentUser {
let idPhotoRoom = self.BASE_REF.child("PhotoRooms").childByAutoId()
idPhotoRoom.setValue(["caption": caption, "StoryPhotoUrlFromStorage": self.storageRef.child(metadata!.path!).description, "fileUrl": self.fileUrl])
}
}
// Story Photo (upload and dowload from server)
func fetchDataFromServer(callback:#escaping (StoryPhoto) -> ()) {
DataService.dataService._PHOTO_REF.observe(.childAdded, with: { (snapshot) in
let photo = StoryPhoto(key: snapshot.key, snapshot: snapshot.value as! Dictionary<String, AnyObject>)
callback(photo)
})
// Sign Up
func signUp(username: String, email: String, password: String, data: NSData) {
FIRAuth.auth()?.createUser(withEmail: email, password: password, completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
return
}
let changeRequest = user?.profileChangeRequest()
changeRequest?.displayName = username
changeRequest?.commitChanges(completion: { (error) in
if let error = error{
print(error.localizedDescription)
return
}
})
let filePath = "profileimage/\(user!.uid)"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpeg"
self.storageRef.child(filePath).put(data as Data, metadata: metaData, completion: { (metadata, error) in
if let error = error {
print("\(error.localizedDescription)")
return
}
self .fileUrl = metadata?.downloadURLs![0].absoluteString
let changeRequestPhoto = user!.profileChangeRequest()
changeRequestPhoto.photoURL = NSURL(string: self.fileUrl) as URL?
changeRequestPhoto.commitChanges(completion: { (error) in
if let error = error {
print(error.localizedDescription)
return
}else{
print("profile uptaded")
}
})
let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.Login()
})
})
}
}
}
}
Sign Up class. Here i am getting error like Value of type DataService has no member "Sign up".
// Register Button
#IBAction func RegisterDidTapped(_ sender: AnyObject) {
guard let email = emailTextField.text, let password = passwordTextField.text, let username = usernameTextField.text else {
return
}
var data = NSData()
data = UIImageJPEGRepresentation(profileImage.image!, 0.1)! as NSData
//Signin up
Here i am getting Error: (Value of type DataService has no member "sign Up")
DataService.dataService.signUp(username: username, email: email, password: password, data: data)
}
}
check correct open and close {}. looks like your signUp function are inside other function.
I am working on one application in which using google plus login
It works fine but I want to integrate with parse also
I have refer for example
func finishedWithAuth(auth: GTMOAuth2Authentication!, error: NSError!) {
let token = auth.accessToken
PFUser.becomeInBackground(token, block: { (user : PFUser?, error : NSError?) -> Void in
if error != nil {
print("Error in become user : \(error)")
} else {
print("user : \(user)")
}
})
}
but it give me error like
Error in become user : Optional(Error Domain=Parse Code=209 "invalid session token" UserInfo={code=209, temporary=0, error=invalid session token, NSLocalizedDescription=invalid session token})
I have try also this example Login with google plus in ios on parse.com
but it is in objective c ,try to convert to swift2 but it also give error
Please give me correct solution
Finally solved issues
convert answer into swift code and its work fine
func finishedWithAuth(auth: GTMOAuth2Authentication!, error: NSError!) {
if error == nil && auth.expirationDate.compare(NSDate(timeIntervalSinceNow: 0)) == NSComparisonResult.OrderedDescending {
let user = GPPSignIn.sharedInstance().googlePlusUser
let userName = user.name.JSONValueForKey("givenName") as! String
let userEmail = GPPSignIn.sharedInstance().userEmail
let pfUser = PFUser()
pfUser.username = userName
pfUser.email = userEmail
let userPassword = "\(userName)#123"
pfUser.password = userPassword
pfUser.signUpInBackgroundWithBlock({ (success, error : NSError?) -> Void in
if error == nil {
let plusService = GTLServicePlus()
plusService.retryEnabled = true
plusService.authorizer = GPPSignIn.sharedInstance().authentication
let query : GTLQueryPlus! = GTLQueryPlus.queryForPeopleGetWithUserId("me") as! GTLQueryPlus
plusService.executeQuery(query, completionHandler: { (ticket, person, error) -> Void in
if error != nil {
print("Error in execute query : \(error!)")
} else {
let aPerson : GTLPlusPerson! = person as! GTLPlusPerson
let imgUrl = aPerson.image.url
if let imgData = NSData(contentsOfURL: NSURL(string: imgUrl)!) {
self.userProfilePic.image = UIImage(data: imgData)
}
let currentUser = PFUser.currentUser()
currentUser?.username = aPerson.displayName
currentUser?.saveInBackground()
}
})
} else {
print("Error in signup : \(error!.localizedDescription)")
PFUser.logInWithUsernameInBackground(self.userName, password: userPassword, block: { (user : PFUser?, error : NSError?) -> Void in
if error == nil {
print("Login Sccessfully")
} else {
print("Error in login : \(error!.localizedDescription)")
}
})
}
})
} else {
print("Error in authentication : \(error.localizedDescription)")
}
}
Hope Help to someone!!!
I don't think it's a matter of incorrect translation to Swift (as the error is generated by Parse itself during the runtime, not the Swift compiler or the Swift runtime). Try using "PFUser.enableRevocableSessionInBackground()". For more details please visit https://parse.com/tutorials/session-migration-tutorial. Hope it'll help you. Cheers.