20

I wonder if there any way to get the original file name using PHAsset?

I use the following code to extract the file info.

   [[PHImageManager defaultManager] requestImageDataForAsset:asset options:requestOption resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
    entity.fileUrl =  [info objectForKey:@"PHImageFileURLKey"];
    entity.filename = [[NSFileManager defaultManager] displayNameAtPath:[ entity.fileUrl path]];
   }];

However, It doesn't return original name but the name in the format "img_123" I've just checked official apple docs . there has been introduced a new class PHAssetResource and the property originalFilename which is available in the iOS 9+. The problem is that I use the image picker library CTAssetsPickerController which 's based on the Photos framework; it returns picked image as the PHAsset object . PS. I'm looking for the solution which is compatible with iOS 8 :). Thank you!

ProblemSlover
  • 2,409
  • 2
  • 20
  • 32

4 Answers4

44

On iOS 8 your solution is the right (and only approach) to get a filename at all.

On iOS 9 this works:

NSArray *resources = [PHAssetResource assetResourcesForAsset:asset];
NSString *orgFilename = ((PHAssetResource*)resources[0]).originalFilename;
holtmann
  • 5,957
  • 30
  • 42
7

Short way to get file name with one line of code. Asset have a property for accessing file name.

 NSString*FileName=[asset valueForKey:@"filename"];
 NSLog(@"File name %@",FileName);

Its done.

Note: Accepted answer takes lots of time to load a phasset but it works.
PlusInfosys
  • 3,234
  • 1
  • 15
  • 32
4

I had to modify my code because it started returning nonsense names. My solution was to pick the resource based on asset's mediaType and resource's type, but maybe there is something easier:

extension PHAsset {
    var primaryResource: PHAssetResource? {
        let types: Set<PHAssetResourceType>

        switch mediaType {
        case .video:
            types = [.video, .fullSizeVideo]
        case .image:
            types = [.photo, .fullSizePhoto]
        case .audio:
            types = [.audio]
        case .unknown:
            types = []
        @unknown default:
            types = []
        }

        let resources = PHAssetResource.assetResources(for: self)
        let resource = resources.first { types.contains($0.type)}

        return resource ?? resources.first
    }

    var originalFilename: String {
        guard let result = primaryResource else {
            return "file"
        }

        return result.originalFilename
    }
}
szotp
  • 1,792
  • 1
  • 14
  • 16
3

Maybe you can use the method, it works above iOS8:

 [asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {

    CIImage *fullImage = [CIImage imageWithContentsOfURL:contentEditingInput.fullSizeImageURL];
    NSLog(@"%@",contentEditingInput.fullSizeImageURL);//get url
    NSLog(@"%@", fullImage.properties.description);//get {TIFF}, {Exif}
}];
Changwei
  • 644
  • 1
  • 5
  • 16
  • Hey thanks. I used an approach suggested in the accepted answer. but after digging in the source(header files) I found that I can use approach similar yours – ProblemSlover Mar 08 '16 at 15:14