Reputation: 8944
I want to get the file name from UIImagePickerController
. I do not want to use ALAssetLibrary because it is deprecated in iOS 9. I have used the following code but it always returns the image name as "Asset.jpg" for each file.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let originalImage = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
let url = info[UIImagePickerControllerReferenceURL] as! NSURL
imageData = UIImageJPEGRepresentation(originalImage, 100) as NSData?
let data = UploadData()
data.fileName = url.lastPathComponent
picker.dismiss(animated: true, completion: nil)
}
Upvotes: 16
Views: 44662
Reputation: 16032
If you are using iOS 15+
, you will not be able to get the image url from a picture taken from the camera because the UIImagePickerController.InfoKey.referenceURL
key is deprecated since iOS 11
, so this is the only solution I found:
First, you need to create an image format enum
:
enum ImageFormat: String {
case png = ".png"
case jpeg = ".jpeg"
case gif = ".gif"
case tiff = ".tiff"
case unknown = ""
init(byte: UInt8) {
switch byte {
case 0x89:
self = .png
case 0xFF:
self = .jpeg
case 0x47:
self = .gif
case 0x49, 0x4D:
self = .tiff
default:
self = .unknown
}
}
}
Then you need this Data
extension property:
extension Data {
var imageFormat: ImageFormat {
guard let header = map({ $0 as UInt8 })[safe: 0] else {
return .unknown
}
return ImageFormat(byte: header)
}
}
And finally:
// MARK: - UIImagePickerControllerDelegate
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
guard let image = info[.editedImage] as? UIImage else {
return
}
var imageName: String?
let data = image.jpegData(compressionQuality: 1)
if let imgUrl = info[UIImagePickerController.InfoKey.imageURL] as? URL {
// If the user pick the picture from the photo library
imageName = imgUrl.lastPathComponent
} else if let metaData = info[UIImagePickerController.InfoKey.mediaMetadata] as? [String: Any],
let tiff = metaData["{TIFF}"] as? [String: Any],
let dateTime = tiff["DateTime"],
let imageFormat = data?.imageFormat {
// If the user take the photo from the camera
imageName = "\(dateTime)\(imageFormat.rawValue)"
}
print(imageName!)
// don't forget to dismiss the picker controller
}
Upvotes: 0
Reputation: 251
import Photos
Before iOS 11
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imageURL = info[UIImagePickerControllerReferenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil)
let assetResources = PHAssetResource.assetResources(for: result.firstObject!)
print(assetResources.first!.originalFilename)
}
dismiss(animated: true, completion: nil)
}
After iOS 11
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let asset = info[UIImagePickerController.InfoKey.phAsset.rawValue] as? PHAsset {
let assetResources = PHAssetResource.assetResources(for: asset)
print(assetResources.first!.originalFilename)
}
dismiss(animated: true, completion: nil)
}
Upvotes: 25
Reputation: 2729
for iOS 11 and above
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// get imageURL and asset
if let asset = info[UIImagePickerController.InfoKey.phAsset] as? PHAsset, let imageURL = info[UIImagePickerController.InfoKey.imageURL] as? URL{
// got asset and imageURL
} else {
// show error
}
dismiss(animated: true, completion: nil)
}
Upvotes: 1
Reputation: 2305
This code is working for me (Swift 5):
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let imgUrl = info[UIImagePickerController.InfoKey.imageURL] as? URL{
let imgName = imgUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let localPath = documentDirectory?.appending(imgName)
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let data = image.pngData()! as NSData
data.write(toFile: localPath!, atomically: true)
let photoURL = URL.init(fileURLWithPath: localPath!)
let filename = photoURL.lastPathComponent
print(filename)
}
picker.dismiss(animated: true, completion: nil)
}
Upvotes: 4
Reputation: 744
i wanted the name of image and tried it, this worked for me hope it work for you as well, you can use phAsset object from uiimagepickercontroller before that PHPhotoLibrary permission is required Note:- before this.......** import Photos **
PHPhotoLibrary.requestAuthorization { (status) in
switch status {
case .notDetermined:
break
case .restricted:
break
case .denied:
break
case .authorized:
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self;
imagePickerController.sourceType = .photoLibrary
let cancelButtonAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes , for: .normal)
imagePickerController.modalPresentationStyle = .fullScreen
self.present(imagePickerController, animated: true, completion: nil)
}
}
@unknown default:
fatalError()
}
}
implement delegate methods of uiimagepicker and add following inside didFinishPickingMediaWithInfo:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if (info[UIImagePickerController.InfoKey.originalImage] as? UIImage) != nil {
if let photoObj = (info[UIImagePickerController.InfoKey.phAsset] as? PHAsset) {
let photoName = pHObjc.localIdentifier
// returns local photo id which will be unique for each photo
}
}
}
Upvotes: 0
Reputation: 808
I came cross this question when searching for a way to retrieve filename from UIImagePickerController
.
I tried all the methods mentioned in the answers, but the results were inconsistent.
As one novice iOS developer my self, I will not try to detail the mechanism between those ways. Instead I will demo my findings.
Note: all under iOS 13 with Swift 5.
The first way, which I don't think it's the really file name because it keeps changing. I guess this is the local path name because image picker saves the image to your app's temporary directory.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let url = info[.imageURL] as? NSURL else { return }
let filename = url.lastPathComponent!
print(filename) // 46484E68-94E8-47B7-B0F4-E52EA7E480A9.jpeg
}
The second way, which is consitent each time I select it. I think it can be used as file name but not flawless.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let photo = info[.phAsset] as? PHAsset
var filename = photo?.value(forKey: "filename") as? String ?? ""
print(filename) // IMG_0228.JPG
}
The third way gets you the original file name, which is the file name you see in your Mac. Say you AirDrop one photo with name "Apple.jpg" to your phone, only with this way will you get the name "Apple.jpg"
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let photo = info[.phAsset] as? PHAsset
let res = PHAssetResource.assetResources(for: photo!)
let filename = res[0].originalFilename
print(filename) // Apple.jpg
}
Upvotes: 1
Reputation: 2211
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var selectedFileName = ""
if #available(iOS 11.0, *) {
if let imageUrl = info[.imageURL] as? URL {
selectedFileName = imageUrl.lastPathComponent
}
} else {
if let imageURL = info[.referenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil)
if let firstObject = result.firstObject {
let assetResources = PHAssetResource.assetResources(for: firstObject)
selectedFileName = assetResources.first?.originalFilename
}
}
}
picker.dismiss(animated: true, completion: nil)
}
Upvotes: 4
Reputation: 3223
Swift 5, iOS 11+
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let photo = info[.phAsset] as? PHAsset
let filename = photo?.value(forKey: "filename") as! String
}
Upvotes: 5
Reputation: 1089
Here is how I did it in swift 4
if let url = info[UIImagePickerController.InfoKey.imageURL] as? URL {
fileName = url.lastPathComponent
fileType = url.pathExtension
}
Upvotes: 19
Reputation: 13537
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
let imageURL = info[UIImagePickerControllerReferenceURL] as NSURL
let imageName = imageURL.path!.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let localPath = documentDirectory.stringByAppendingPathComponent(imageName)
let image = info[UIImagePickerControllerOriginalImage] as UIImage
let data = UIImagePNGRepresentation(image)
data.writeToFile(localPath, atomically: true)
let imageData = NSData(contentsOfFile: localPath)!
let photoURL = NSURL(fileURLWithPath: localPath)
let imageWithData = UIImage(data: imageData)!
picker.dismissViewControllerAnimated(true, completion: nil)
}
Upvotes: 1
Reputation: 2046
For me, it is working perfect,
if let imgUrl = info[UIImagePickerControllerImageURL] as? URL{
let imgName = imgUrl.lastPathComponent
print(imgName)
let imgExtension = imgUrl.pathExtension
print(imgExtension)
}
Upvotes: -1
Reputation: 601
Update 6th May 2018
Forced unwrapped optionals sometimes return nil
, I think it's because user use Camera to capture a new image instead of selecting one from Photos library. I updated the code to return a generated name when I see nil.
Original answer
This works for me without having to rely on filename
key (please excuse for force unwrap optionals :) )
extension MyViewController : UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let image = info[UIImagePickerControllerEditedImage] as? UIImage else {
DDLogDebug("No image chosen")
return
}
if let url = info[UIImagePickerControllerReferenceURL] as? URL {
let assets = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
if let firstAsset = assets.firstObject,
let firstResource = PHAssetResource.assetResources(for: firstAsset).first {
fileName = firstResource.originalFilename
} else {
fileName = generateNameForImage()
}
} else {
fileName = generateNameForImage()
}
DDLogDebug("File name = \(fileName)")
dismiss(animated: true)
}
func generateNameForImage() -> String {
return "IMG_random_string"
}
}
Upvotes: 6
Reputation: 267
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let asset = PHAsset.fetchAssets(withALAssetURLs: [info[UIImagePickerControllerReferenceURL] as! URL],options: nil).firstObject {
var resources = PHAssetResource.assetResources(for: asset)
let orgFilename: String = ((resources[0] as? PHAssetResource)?.originalFilename)!
print("filename:",orgFilename)
}
}
Upvotes: -1
Reputation: 2178
You can try this for iOS 11
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let asset = info[UIImagePickerControllerPHAsset] as? PHAsset {
if let fileName = (asset.value(forKey: "filename")) as? String {
//Do your stuff here
}
}
picker.dismiss(animated: true, completion: nil)
}
Make sure you add this NSPhotoLibraryUsageDescription to your Infor.plist
Upvotes: 2
Reputation: 1609
import Photos
func getFileName(info: [String : Any]) -> String {
if let imageURL = info[UIImagePickerControllerReferenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil)
let asset = result.firstObject
let fileName = asset?.value(forKey: "filename")
let fileUrl = URL(string: fileName as! String)
if let name = fileUrl?.deletingPathExtension().lastPathComponent {
print(name)
return name
}
}
return ""
}
call it inside the method "didFinishPickingMediaWithInfo" like so:
let fileName = getFileName(info: info)
Upvotes: 1
Reputation: 11127
I will suggest you to use Photos
Framework to get the name of the image, below is the code to get name of selected image
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)
}
Upvotes: 23