The file “IMG_0001.JPG” couldn’t be opened because you don’t have permission to view it - swift

I'm using JSQMessagesViewController to send photo messages in my chats and I face this problem when I'm trying to upload image from gallery. Here is my code:
override func didPressAccessoryButton(_ sender: UIButton) {
let picker = UIImagePickerController()
picker.delegate = self
if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary)) {
picker.sourceType = UIImagePickerControllerSourceType.photoLibrary
}
present(picker, animated: true, completion:nil)
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any]) {
picker.dismiss(animated: true, completion:nil)
// 1
if let photoReferenceUrl = info[UIImagePickerControllerReferenceURL] as? URL {
// Handle picking a Photo from the Po8hoto Library
// 2
let assets = PHAsset.fetchAssets(withALAssetURLs: [photoReferenceUrl], options: nil)
let asset = assets.firstObject
// 3
if let key = sendPhotoMessage() {
// 4
asset?.requestContentEditingInput(with: nil, completionHandler: { (contentEditingInput, info) in
let imageFileURL = contentEditingInput?.fullSizeImageURL
// 5
let path = "\(FIRAuth.auth()?.currentUser?.uid)/\(Int(Date.timeIntervalSinceReferenceDate * 1000))/\(photoReferenceUrl.lastPathComponent)"
// 6
self.storageRef.child(path).putFile(imageFileURL!, metadata: nil) { (metadata, error) in
if let error = error {
print("Error uploading photo: \(error.localizedDescription)")
return
}
// 7
self.setImageURL(self.storageRef.child((metadata?.path)!).description, forPhotoMessageWithKey: key)
}
})
}
} else {
// Handle picking a Photo from the Camera - TODO
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion:nil)
}
I`ve read a lot about it in google ( The file “xxx.mp4” couldn’t be opened because you don’t have permission to view it ) , but unfortunately, there is no solution for it. Please help me to understand how could I fix this warning?
Whole warning message:
Body file is unreachable:
/var/mobile/Media/PhotoData/Sync/100SYNCD/IMG_0001.JPG Error
Domain=NSCocoaErrorDomain Code=257 "The file “IMG_0001.JPG” couldn’t
be opened because you don’t have permission to view it."
UserInfo={NSURL=file:///var/mobile/Media/PhotoData/Sync/100SYNCD/IMG_0001.JPG, NSFilePath=/var/mobile/Media/PhotoData/Sync/100SYNCD/IMG_0001.JPG,
NSUnderlyingError=0x17464d4a0 {Error Domain=NSPOSIXErrorDomain Code=1
"Operation not permitted"}} Error uploading photo: An unknown error
occurred, please check the server response.
P.S. this works good in emulator, I'm getting this warning only at real device.

I've rewrite imagePickerController method, now it works perfect
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any]) {
picker.dismiss(animated: true, completion:nil)
let stRef = FIRStorage.storage().reference()
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpeg"
if let photo = info[UIImagePickerControllerOriginalImage] as? UIImage {
var data = NSData()
data = UIImageJPEGRepresentation(photo, 0.25)! as NSData
if let key = sendPhotoMessage() {
let path = "\(FIRAuth.auth()?.currentUser?.uid)/\(Int(Date.timeIntervalSinceReferenceDate * 1000)))"
stRef.child(path).put(data as Data, metadata: metaData){ (metaData,error) in
if error != nil {
return
}
else {
let downloadURL = metaData!.downloadURL()!.absoluteString
self.setImageURL(downloadURL, forPhotoMessageWithKey: key)
}
}
}
} else {
// Handle picking a Photo from the Camera - TODO
}
}

Related

How to get filename when using PHPickerViewController for photo

How to get filename when using PHPickerViewController for photo
this is my function code
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true, completion: nil)
for item in results {
item.itemProvider.loadObject(ofClass: UIImage.self) {(image, error) in
if let image = image as? UIImage{
}
}
}
}
Please help, thank you
Hope you van find file name by using this:
item.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.item") { (url, error) in
if error != nil {
print("error \(error!)");
} else {
if let url = url {
let filename = url.lastPathComponent;
print(filename)
}
}
}
You can use this to get file name from UIImagePickerController
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imageURL = info[UIImagePickerControllerReferenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil)
let asset = result.firstObject
print(asset?.value(forKey: "filename"))
}
dismiss(animated: true, completion: nil)
}
The NSItemProvider from PHPickerResult has a suggestedName property that will give you the file name. So from your provided code:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true, completion: nil)
for item in results {
item.itemProvider.loadObject(ofClass: UIImage.self) {(image, error) in
// This will give you the file name
guard let fileName = item.itemProvider.suggestedName else { return }
if let image = image as? UIImage{
}
}
}
}

Upload image to Firebase Storage and show as Profile Image

I need help with uploading image to Firebase Storage. I have a profile menu in my app. When user tap on this menu he/she can see profile with their info and Profile Image. So I made it so you can select a photo from the gallery. But I need to save photo to Firebase Storage and add ref to Firebase Database by uid.
In addition, the user may not have a photo, so it will be nill because nothing in Database. Look at photo and you will understand everything
extension ProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var selectedImage: UIImage?
if let editedImage = info[.editedImage] as? UIImage {
selectedImage = editedImage
self.profileImage.image = selectedImage!
self.savedImage = selectedImage
picker.dismiss(animated: true, completion: nil)
} else if let originalImage = info[.originalImage] as? UIImage {
selectedImage = originalImage
self.profileImage.image = selectedImage!
self.savedImage = selectedImage
picker.dismiss(animated: true, completion: nil)
}
}
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView) )
profileImage.addGestureRecognizer(tapGesture)
profileImage.isUserInteractionEnabled = true
#objc func handleSelectProfileImageView () {
print("Tapped")
let pickerController = UIImagePickerController()
pickerController.delegate = self
present(pickerController, animated: true, completion: nil)
}
So, how to upload and dowload image.
If the user does not have a photo (ref in Database). He will see image from assets.
If the user have photo he will see image from FB.
image
For Uploading to Firebase storage
let imgData: NSData = NSData(data: UIImageJPEGRepresentation((self.img_Photo?.image)!, 0.5)!)
let _:NSData = NSData(data:UIImagePNGRepresentation(((self.img_Photo?.image)!))!)
self.uploadProfileImageToFirebase(data: imgData)
Function for uploading
func uploadProfileImageToFirebase(data:NSData){
let randomPic = randomString(length: 10)
let storageRef = Storage.storage().reference().child("Pictures").child("\(value(forKey: "UserUID") ?? 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) ?? ""
let values = ["photo_url": urlStr]
self.registerUserIntoDatabaseWithUID(uid: userID, values: values as [String : AnyObject])
}
}
})
}
}
func registerUserIntoDatabaseWithUID(uid:String, values:[String:AnyObject]){
let ref = Database.database().reference(fromURL: "https://domain.firebaseio.com/")
let usersReference = ref.child("users").child((Auth.auth().currentUser?.uid)!)
usersReference.updateChildValues(values) { (error, ref) in
if(error != nil){
print(error)
return
}
self.parentVC?.dismiss(animated: true, completion: nil)
}
}

Upload image to Firebase from UIImagePicker

I would like to upload a profile picture to Firebase when my UIImage picker has been chosen. But I don't know how to do it and
I can not understand the documentation, because I'm new in coding). Please, help me. I need to upload picture to Firebase. It will be user picture, so reference to picture should save to Database.
extension ProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
profileImage.image = image
picker.dismiss(animated: true, completion: nil)
}
I don't how to upload and dowload profile image.
Create a storage reference and add folder name and image names.
Storage.storage().reference().child("id").child("profile.png")
and use putData:metadata:completion: method to upload the image. Once image has been uploaded get the image url and update it in user details.
Upload profile image
import FirebaseStorage
import FirebaseAuth
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.originalImage] as? UIImage, let imageData = image.pngData() {
profileImage.image = image
let storageRef = Storage.storage().reference().child("id").child("profile.png")
let metaData = StorageMetadata()
metaData.contentType = "image/png"
storageRef.putData(imageData, metadata: metaData) { (metaData, error) in
if error == nil, metaData != nil {
storageRef.downloadURL { url, error in
if let url = url {
print(url)//URL of the profile image
self.saveProfileImageUrlInUserDetails(url: url)
}
}
} else {
print(error?.localizedDescription)//upload failed
}
}
}
picker.dismiss(animated: true, completion: nil)
}
Save uploaded photo reference in user detail Update the user's profile
func saveProfileImageUrlInUserDetails(url: URL) {
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.photoURL = url
changeRequest?.commitChanges(completion: { error in
if error == nil {
//saved
} else {
print(error?.localizedDescription)//failed to udpate
}
})
}
Download profile image
if let profileImgUrl = Auth.auth().currentUser?.photoURL?.absoluteString {
let ref = Storage.storage().reference(forURL: profileImgUrl)
ref.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print(error.localizedDescription)
} else if let data = data, let image = UIImage(data: data) {
self.profileImage.image = image
}
}
}

Firebase storage

I tried to upload images into firebase storage, and fyi my app is under firebase phone number Auth registration. And here is my code for uploading images:
#IBAction func addBtnClicked(_ sender: UIButton) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var selectedImageFromPicker: UIImage?
if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage {
selectedImageFromPicker = editedImage
} else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage {
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker {
imageView.image = selectedImage
}
let storageRef = Storage.storage().reference().child("profile_images").child("test01.png")
if let uploadData = UIImagePNGRepresentation(self.imageView.image!) {
storageRef.putData(uploadData, metadata: nil) { (metadata, error) in
if let error = error {
print(error)
return
}
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("canceled picker")
dismiss(animated: true, completion: nil)
}
But every time after I compiled, I got this error code:
User does not have permission to access gs://cal-dev.appspot.com/profile_images/test01.png." UserInfo={object=profile_images/test01.png, ResponseBody={
"error": {
"code": 403,
"message": "Permission denied. Could not perform this operation"
}
Have you given read and write access in your firebase console? It seems that you are not authorized to write data to firebase..

didFinishPickingMediaWithInfo function goes on infinite loop

It looks like the didFinishPickingMediaWithInfo function is going on an infinite loop and it eventually crashes with an error that says in the console:
warning: could not execute support code to read Objective-C class data in >the process. This may reduce the quality of type information available.
Right when I record a video and press the choose button, it crashes because it calls the didFinishPickingMediaWithInfo. Here is the relevant code:
let imagePicker: UIImagePickerController! = UIImagePickerController()
let saveFileName = "/test.mp4"
if (UIImagePickerController.isSourceTypeAvailable(.camera)) {
if UIImagePickerController.availableCaptureModes(for: .rear) != nil {
//if the camera is available, and if the rear camera is available, the let the image picker do this
imagePicker.sourceType = .camera
imagePicker.mediaTypes = [kUTTypeMovie as String]
imagePicker.allowsEditing = false
imagePicker.delegate = self as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
imagePicker.videoMaximumDuration = 60
imagePicker.videoQuality = .typeIFrame1280x720
present(imagePicker, animated: true, completion: nil)
} else {
postAlert("Rear camera doesn't exist", message: "Application cannot access the camera.")
}
} else {
postAlert("Camera inaccessable", message: "Application cannot access the camera.")
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print(123)
imagePickerController(imagePicker, didFinishPickingMediaWithInfo: [saveFileName : kUTTypeMovie])
let videoURL = info[UIImagePickerControllerReferenceURL] as? NSURL
print("\(String(describing: videoURL))" )
guard let path = videoURL?.path else { return }
let videoName = path.lastPathComponent
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentDirectory = paths.first as String!
let localPath = documentDirectory! + "/" + videoName
guard let imageData = NSData(contentsOfFile: localPath) else { return }
let image = UIImage(data: imageData as Data)
picker.dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.imagePicker.delegate = self
}
Thank you in advance!
You are calling the function from inside of itself, here:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print(123)
imagePickerController(imagePicker, didFinishPickingMediaWithInfo: [saveFileName : kUTTypeMovie])
That is causing your infinite loop.