如何使用资产库获取 UIImagePickerController 中的文件名?

How to get file name in UIImagePickerController with Asset library?

我想从 UIImagePickerController 获取文件名。我不想使用 ALAssetLibrary,因为它在 iOS 9 中已被弃用。我使用了以下代码,但它总是 returns 每个文件的图像名称为 "Asset.jpg"。

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

代码:

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

我会建议你使用Photos框架来获取图像的名称,下面是获取所选图像名称的代码

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

2018 年 5 月 6 日更新

有时强制解包选项 return nil,我认为这是因为用户使用相机拍摄新图像而不是从照片库中选择图像。当我看到 nil 时,我将代码更新为 return 生成的名称。

原回答

这对我有用,无需依赖 filename 键(请原谅强制解包选项:))

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

}

导入照片

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

}

在方法 "didFinishPickingMediaWithInfo" 中调用它,如下所示:

let fileName = getFileName(info: info)

你可以试试 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)
}

确保将此 NSPhotoLibraryUsageDescription 添加到您的 Infor.plist

之前 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)
}

iOS11

之后
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let asset = info[UIImagePickerControllerPHAsset] as? PHAsset {
        let assetResources = PHAssetResource.assetResources(for: asset)

        print(assetResources.first!.originalFilename)
    }

    dismiss(animated: true, completion: nil)
}
  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)
     }
    }
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)
}

对我来说,它工作完美,

if let imgUrl = info[UIImagePickerControllerImageURL] as? URL{
   let imgName = imgUrl.lastPathComponent
   print(imgName)
   let imgExtension = imgUrl.pathExtension
   print(imgExtension)
}

这是我在 swift 4

中的做法
if let url = info[UIImagePickerController.InfoKey.imageURL] as? URL {
        fileName = url.lastPathComponent
        fileType = url.pathExtension
    }
    let fileName = (info[.imageURL] as? URL)?.lastPathComponent

Swift5,iOS11+

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    let photo = info[.phAsset] as? PHAsset
    let filename = photo?.value(forKey: "filename") as! String
}

我在搜索从 UIImagePickerController 检索文件名的方法时遇到了这个问题。

答案中提到的方法我都试过了,结果都不一致

作为一名新手 iOS 自己开发,我不会尝试详细说明这些方法之间的机制。相反,我将演示我的发现。

注意:所有在 iOS 13 和 Swift 5.

第一种方式,我不认为它是真正的文件名,因为它一直在变化。我想这是本地路径名,因为图像选择器会将图像保存到您应用的临时目录中。

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
}

第二种方式,我每次都是一致的select。我认为它可以用作文件名但不是完美无缺

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
}

第三种方式获取原始文件名,即您在 Mac 中看到的文件名。假设你 AirDrop 一张名称为“Apple.jpg”的照片到你的 phone,只有这样你才能得到名称“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
}

我想要图像的名称并尝试了它,这对我有用希望它对你也有用,你可以在需要 PHPhotoLibrary 权限之前使用 uiimagepickercontroller 中的 phAsset 对象 注意:- 在此之前......** 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()
        }
    }

实现 uiimagepicker 的委托方法并在 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
     }
   }
}

这段代码对我有用 (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)
}

对于 iOS 11 岁及以上

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