Ich bin daran interessiert, den MIME-Typ für eine Datei im Dokumentenverzeichnis meiner iPhone-Anwendung zu ermitteln. Eine Suche in den Dokumenten lieferte keine Antworten.
Es ist ein bisschen hackig, aber es sollte funktionieren, weiß es nicht genau, weil ich es nur vermute
Es gibt zwei Möglichkeiten:
Stellen Sie jedoch sicher, dass Sie die Anforderung in einem Thread ausführen, da sie synchron ist.
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];
Fügen Sie MobileCoreServices framework hinzu.
Ziel 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);
Schnell:
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
}
Die akzeptierte Antwort ist für große Dateien problematisch, wie andere bereits erwähnt haben. Meine App beschäftigt sich mit Videodateien. Wenn Sie eine komplette Videodatei in den Arbeitsspeicher laden, können Sie dafür sorgen, dass iOS nicht mehr über genügend Arbeitsspeicher verfügt. Einen besseren Weg finden Sie hier:
https://stackoverflow.com/a/5998683/1864774
Code vom obigen 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];
}
Prcela Lösung funktionierte nicht in Swift 2 . Die folgende vereinfachte Funktion gibt den Mime-Typ für eine bestimmte Dateierweiterung in Swift 2 zurück:
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
}
Ich verwendete die Antwort von slf in einer Kakao-App (nicht iPhone) und bemerkte, dass die URL-Anforderung die gesamte Datei von der Festplatte zu lesen scheint, um den Mime-Typ zu bestimmen (nicht ideal für große Dateien).
Für jeden, der dies auf dem Desktop tun möchte, ist hier der von mir verwendete Ausschnitt (basierend auf Louis 'Vorschlag):
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;
}
Wenn Sie das in einer PDF -Datei aufrufen, würde dies auslaufen: application/pdf
Basierend auf der Antwort von Lawrence Dol/slf oben habe ich die NSURL beim Laden der gesamten Datei in den Speicherproblem gelöst, indem ich die ersten paar Bytes in einen Head-Stub zerhackt und den MIMEType davon erhalte. Ich habe es nicht getestet, aber es ist wahrscheinlich auch schneller so.
+ (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;
}
Unter Mac OS X wird dies über LaunchServices und UTIs abgewickelt. Auf dem iPhone sind diese nicht verfügbar. Da die einzige Möglichkeit, Daten in Ihre Sandbox zu bekommen, darin besteht, sie dort abzulegen, verfügen die meisten Apps über fundiertes Wissen über die Daten aller Dateien, die sie lesen können.
Wenn Sie eine solche Funktion benötigen, sollten Sie file eine Funktionsanforderung bei Apple anfordern.
Ich bin nicht sicher, was die Praktiken auf dem iPhone sind, aber wenn Sie dazu berechtigt sind, würde ich hier die UNIX-Philosophie verwenden: Verwenden Sie das Programm file
, das die Standardmethode zum Erkennen von Dateitypen auf einem UNIX-Betriebssystem ist. Es enthält eine umfangreiche Datenbank mit magischen Markern für die Erkennung von Dateitypen. Da file
wahrscheinlich nicht auf dem iPhone ausgeliefert wird, können Sie es in Ihr App-Paket aufnehmen. Möglicherweise gibt es eine Bibliothek, die die Funktionalität von file
implementiert.
Alternativ können Sie dem Browser vertrauen. Browser senden den ermittelten MIME-Typ irgendwo in den HTTP-Headern. Ich weiß, dass ich die Informationen zum MIME-Typ in PHP problemlos abrufen kann. Das hängt natürlich davon ab, ob Sie dem Kunden vertrauen wollen.