objective-c 如何在objective-c中读取MIME类型的文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1363813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can you read a files MIME-type in objective-c
提问by coneybeare
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.
我对在我的 iPhone 应用程序的文档目录中检测文件的 MIME 类型感兴趣。通过文档搜索没有提供任何答案。
回答by slf
It's a bit hacky, but it should work, don't know for sure because I'm just guessing at it
这有点hacky,但它应该可以工作,不确定,因为我只是在猜测
There are two options:
有两种选择:
- If you just need the MIME type, use the timeoutInterval: NSURLRequest.
- If you want the data as well, you should use the commented out NSURLRequest.
- 如果您只需要 MIME 类型,请使用 timeoutInterval: NSURLRequest。
- 如果你也想要数据,你应该使用注释掉的 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];
回答by Prcela
Add MobileCoreServicesframework.
添加MobileCoreServices框架。
Objective C:
目标 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
}
回答by Adam Lockhart
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:
正如其他人所提到的,接受的答案对于大文件是有问题的。我的应用程序处理视频文件,将整个视频文件加载到内存中是让 iOS 内存不足的好方法。可以在此处找到更好的方法:
https://stackoverflow.com/a/5998683/1864774
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];
}
回答by dreamlab
Prcelasolutiondid not work in Swift 2. The following simplified function will return the mime-type for a given file extension in Swift 2:
Prcela解决方案在Swift 2 中不起作用。以下简化函数将返回 Swift 2 中给定文件扩展名的 MIME 类型:
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
}
回答by danw
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).
我在可可应用程序(不是 iPhone)中使用 slf 提供的答案,并注意到 URL 请求似乎正在从磁盘读取整个文件以确定 mime 类型(不适用于大文件)。
For anyone wanting to do this on the desktop here is the snippet I used (based on Louis's suggestion):
对于任何想在桌面上执行此操作的人,这里是我使用的代码段(基于 Louis 的建议):
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
如果你在 PDF 文件上调用它,它会吐出:application/pdf
回答by got nate
Based on the Lawrence Dol/slf answer above, I have solved the NSURL loading the entire file into memory issue by chopping the first few bytes into a head-stub and getting the MIMEType of that. I have not benchmarked it, but it's probably faster this way too.
根据上面的 Lawrence Dol/slf 答案,我通过将前几个字节切入头存根并获取其 MIMEType 解决了 NSURL 将整个文件加载到内存中的问题。我没有对它进行基准测试,但它也可能更快。
+ (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;
}
回答by Louis Gerbarg
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.
在 Mac OS X 上,这将通过 LaunchServices 和 UTI 处理。在 iPhone 上,这些不可用。由于数据进入您的沙箱的唯一方法是让您将其放在沙箱中,因此大多数应用程序对它们可以读取的任何文件的数据具有内在的知识。
If you have a need for such a feature you should filea feature request with Apple.
如果您需要此类功能,则应向 Apple提交功能请求。
回答by Ivan Vu?ica
I'm not sure what are the practices on iPhone, but if you're allowed to, I'd make use of UNIX philosophy here: use program file, which is the standard way to detect filetype on an UNIX operating system. It includes a vast database of magic markers for filetype detection. Since fileis probably not shipped on iPhone, you could include it in your app bundle. There might be a library implementing file's functionality.
我不确定 iPhone 上的做法是什么,但如果允许的话,我会在这里使用 UNIX 哲学: use program file,这是在 UNIX 操作系统上检测文件类型的标准方法。它包括一个庞大的用于文件类型检测的魔法标记数据库。由于file可能未在 iPhone 上提供,您可以将其包含在您的应用程序包中。可能有一个库实现了file的功能。
Alternatively, you could trust the browser. Browsers send the MIME type they guessed somewhere in the HTTP headers. I know that I can easily grab the MIME type information in PHP. That of course depends if you're willing to trust the client.
或者,您可以信任浏览器。浏览器将他们猜测的 MIME 类型发送到 HTTP 标头中的某处。我知道我可以轻松地在 PHP 中获取 MIME 类型信息。这当然取决于您是否愿意信任客户。
回答by Hari Narayanan
Make sure are you import the coreservices
确保您导入了核心服务
import <CoreServices/CoreServices.h>
import <CoreServices/CoreServices.h>
in your file.
在您的文件中。

