我想检测iPhone应用程序的文档目录中文件的MIME类型。在查看文档时没有找到任何答案。
我想检测iPhone应用程序的文档目录中文件的MIME类型。在查看文档时没有找到任何答案。
这个方法有些不太正规,但应该可以工作,我不能确定因为只是猜测。
有两个选项:
请确保在一个线程中执行请求,因为它是同步的。
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];
connection:didReceiveResponse:
中分析响应。 - user207128[NSURLRequest -initWithURL:cachePolicy:timeoutInterval:]
中的cachePolicy
类型是NSURLRequestCachePolicy
而不是NSURLCacheStoragePolicy
。无论如何,感谢您的发布。 - WeZZard添加MobileCoreServices框架。
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
}
mimeType(fileExtension: myUrl.pathExtension)
代替mimeType(fileExtension: myUrl)
。 - Ky -正如其他人所指出的那样,对于大文件,接受的答案存在问题。我的应用程序处理视频文件,将整个视频文件加载到内存中是让iOS耗尽内存的好方法。这里可以找到更好的方法:
https://dev59.com/Jm025IYBdhLWcg3wc1tM#5998683
来自上述链接的代码:
+ (NSString*) mimeTypeForFileAtPath: (NSString *) path {
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
return nil;
}
// Borrowed from https://dev59.com/Jm025IYBdhLWcg3wc1tM
// itself, derived from https://dev59.com/nnE95IYBdhLWcg3wI6ft
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];
}
autorelease
调用并在函数中添加@autoreleasepool{}
块。 - YogiPrcela solution在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
}
我在使用slf提供的答案时注意到,URL请求似乎需要读取整个文件以确定mime类型(对于大文件不太友好),这是在一个cocoa应用程序中(不是iPhone)。
如果有人想在桌面上实现这一功能,这是我使用的代码片段(基于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;
}
基于上面的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;
}
请确保在您的文件中导入了coreservices
import <CoreServices/CoreServices.h>
。
我不确定iPhone上的惯例是什么,但如果允许的话,我会在这里使用UNIX哲学:使用程序file
,它是在UNIX操作系统上检测文件类型的标准方式。它包括用于文件类型检测的大量魔术标记的数据库。由于file
可能没有在iPhone上安装,您可以将其包含在应用程序包中。可能有一个实现file
功能的库。
或者,您可以信任浏览器。浏览器在HTTP头中发送他们猜测的MIME类型。我知道我可以轻松地在PHP中获取MIME类型信息。当然,这取决于您是否愿意信任客户端。