如何在objective-c中读取MIME类型的文件

时间:2009-09-01 18:03:45

标签: iphone objective-c mime mime-types

我有兴趣检测iPhone应用程序的文档目录中的文件的MIME类型。通过文档搜索没有提供任何答案。

9 个答案:

答案 0 :(得分:54)

有点hacky,但它应该有效,不知道肯定是因为我只是猜测它

有两种选择:

  1. 如果您只需要MIME类型,请使用timeoutInterval:NSURLRequest。
  2. 如果您还想要数据,则应使用注释掉的NSURLRequest。
  3. 确保在线程中执行请求,因为它是同步的。

    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];
    

答案 1 :(得分:41)

添加MobileCoreServices框架。

目标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);

夫特:

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
}

答案 2 :(得分:10)

正如其他人所提到的,对于大文件,已接受的答案是有问题的。我的应用程序处理视频文件,并将整个视频文件加载到内存中是一种使iOS内存不足的好方法。可以在此处找到更好的方法:

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

以上链接的代码:

+ (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];
}

答案 3 :(得分:6)

Prcela solution无效 Swift 2 。以下简化函数将返回Swift 2中给定文件扩展名的mime-type:

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
}

答案 4 :(得分:5)

我正在使用slf在cocoa应用程序(而不是iPhone)中提供的答案,并注意到URL请求似乎是从磁盘读取整个文件以确定mime类型(对于大文件来说不是很好)。 / p>

对于想要在桌面上执行此操作的任何人,这里是我使用的代码段(基于路易斯的建议):

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

如果您在PDF文件上调用它,它会吐出:application / pdf

答案 5 :(得分:4)

基于the Lawrence Dol/slf answer above,我已经解决了NSURL将整个文件加载到内存问题中,方法是将前几个字节切入头部存根并获取其中的MIMEType。我没有对它进行基准测试,但这种方式也可能更快。

+ (NSString*) mimeTypeForFileAtPath: (NSString *) path {
    // NSURL will read the entire file and may exceed available memory if the file is large enough. Therefore, we will write the first fiew bytes of the file to a head-stub for NSURL to get the MIMEType from.
    NSFileHandle *readFileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
    NSData *fileHead = [readFileHandle readDataOfLength:100]; // we probably only need 2 bytes. we'll get the first 100 instead.

    NSString *tempPath = [NSHomeDirectory() stringByAppendingPathComponent: @"tmp/fileHead.tmp"];

    [[NSFileManager defaultManager] removeItemAtPath:tempPath error:nil]; // delete any existing version of fileHead.tmp
    if ([fileHead writeToFile:tempPath atomically:YES])
    {
        NSURL* fileUrl = [NSURL fileURLWithPath:path];
        NSURLRequest* fileUrlRequest = [[NSURLRequest alloc] initWithURL:fileUrl cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:.1];

        NSError* error = nil;
        NSURLResponse* response = nil;
        [NSURLConnection sendSynchronousRequest:fileUrlRequest returningResponse:&response error:&error];
        [[NSFileManager defaultManager] removeItemAtPath:tempPath error:nil];
        return [response MIMEType];
    }
    return nil;
}

答案 6 :(得分:1)

在Mac OS X上,这将通过LaunchServices和UTI来处理。在iPhone上这些不可用。由于数据进入沙箱的唯一方法是让您将其放入其中,因此大多数应用程序都具有关于他们可以阅读的任何文件的数据的内在知识。

如果您需要此类功能,则应向file提出Apple的功能请求。

答案 7 :(得分:0)

我不确定iPhone上的做法是什么,但如果你被允许,我会在这里使用UNIX哲学:使用程序file,这是检测文件类型的标准方法一个UNIX操作系统。它包括用于文件类型检测的大量魔术标记数据库。由于iPhone上可能未提供file,因此您可以将其包含在应用包中。可能有一个库实现file的功能。

或者,您可以信任浏览器。浏览器会在HTTP标头中的某处发送他们猜到的MIME类型。我知道我可以轻松地在PHP中获取MIME类型信息。当然,这取决于您是否愿意信任客户。

答案 8 :(得分:0)

确保您要导入核心服务

import <CoreServices/CoreServices.h>

在您的文件中。