How can you read a files MIME-type in objective-c

后端 未结 9 1596
伪装坚强ぢ
伪装坚强ぢ 2020-12-01 01:50

I am interested in detecting the MIME-type for a file in the documents directory of my iPhone application. A search through the docs did not provide any answers.

相关标签:
9条回答
  • 2020-12-01 02:31

    On Mac OS X this would be handled through LaunchServices and UTIs. On the iPhone these are not available. Since the only way for data to get into your sandbox is for you to put it there, most apps have intrinsic knowledge about the data of any file they can read.

    If you have a need for such a feature you should file a feature request with Apple.

    0 讨论(0)
  • 2020-12-01 02:36

    It's a bit hacky, but it should work, don't know for sure because I'm just guessing at it

    There are two options:

    1. If you just need the MIME type, use the timeoutInterval: NSURLRequest.
    2. If you want the data as well, you should use the commented out NSURLRequest.

    Make sure to perform the request in a thread though, since it's synchronous.

    NSString* filePath = [[NSBundle mainBundle] pathForResource:@"imagename" ofType:@"jpg"];
    NSString* fullPath = [filePath stringByExpandingTildeInPath];
    NSURL* fileUrl = [NSURL fileURLWithPath:fullPath];
    //NSURLRequest* fileUrlRequest = [[NSURLRequest alloc] initWithURL:fileUrl];
    NSURLRequest* fileUrlRequest = [[NSURLRequest alloc] initWithURL:fileUrl cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:.1];
    
    NSError* error = nil;
    NSURLResponse* response = nil;
    NSData* fileData = [NSURLConnection sendSynchronousRequest:fileUrlRequest returningResponse:&response error:&error];
    
    fileData; // Ignore this if you're using the timeoutInterval
              // request, since the data will be truncated.
    
    NSString* mimeType = [response MIMEType];
    
    [fileUrlRequest release];
    
    0 讨论(0)
  • 2020-12-01 02:46

    The accepted answer is problematic for large files, as others have mentioned. My app deals with video files, and loading an entire video file into memory is a good way to make iOS run out of memory. A better way to do this can be found here:

    https://stackoverflow.com/a/5998683/1864774

    Code from above link:

    + (NSString*) mimeTypeForFileAtPath: (NSString *) path {
      if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
        return nil;
      }
      // Borrowed from https://stackoverflow.com/questions/5996797/determine-mime-type-of-nsdata-loaded-from-a-file
      // itself, derived from  https://stackoverflow.com/questions/2439020/wheres-the-iphone-mime-type-database
      CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[path pathExtension], NULL);
      CFStringRef mimeType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
      CFRelease(UTI);
      if (!mimeType) {
        return @"application/octet-stream";
      }
      return [NSMakeCollectable((NSString *)mimeType) autorelease];
    }
    
    0 讨论(0)
  • 2020-12-01 02:46

    Prcela solution did not work in Swift 2. The following simplified function will return the mime-type for a given file extension in Swift 2:

    import MobileCoreServices
    
    func mimeTypeFromFileExtension(fileExtension: String) -> String? {
        guard let uti: CFString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension as NSString, nil)?.takeRetainedValue() else {
            return nil
        }
    
        guard let mimeType: CFString = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() else {
            return nil
        }
    
        return mimeType as String
    }
    
    0 讨论(0)
  • 2020-12-01 02:47

    Add MobileCoreServices framework.

    Objective C:

    #import <MobileCoreServices/MobileCoreServices.h>    
    NSString *fileExtension = [myFileURL pathExtension];
    NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtension, NULL);
    NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
    

    Swift:

    import MobileCoreServices
    
    func mimeType(fileExtension: String) -> String? {
    
        guard !fileExtension.isEmpty else { return nil }
    
        if let utiRef = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension as CFString, nil) {
            let uti = utiRef.takeUnretainedValue()
            utiRef.release()
    
            if let mimeTypeRef = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType) {
                let mimeType = MIMETypeRef.takeUnretainedValue()
                mimeTypeRef.release()
                return mimeType as String
            }
        }
    
        return nil
    }
    
    0 讨论(0)
  • 2020-12-01 02:51

    I was using the answer provided by slf in a cocoa app (not iPhone) and noticed that the URL request seems to be reading the entire file from disk in order to determine the mime type (not great for large files).

    For anyone wanting to do this on the desktop here is the snippet I used (based on Louis's suggestion):

    NSString *path = @"/path/to/some/file";
    
    NSTask *task = [[[NSTask alloc] init] autorelease];
    [task setLaunchPath: @"/usr/bin/file"];
    [task setArguments: [NSArray arrayWithObjects: @"-b", @"--mime-type", path, nil]];
    
    NSPipe *pipe = [NSPipe pipe];
    [task setStandardOutput: pipe];
    
    NSFileHandle *file = [pipe fileHandleForReading];
    
    [task launch];
    [task waitUntilExit];
    if ([task terminationStatus] == YES) {
        NSData *data = [file readDataToEndOfFile];
        return [[[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding] autorelease];
    } else {
        return nil;
    }
    

    If you called that on a PDF file it would spit out: application/pdf

    0 讨论(0)
提交回复
热议问题