2008-11-19 3 views
4

Мое приложение является зрителем для пользовательского формата, zip-файла с четко определенным XML-манифестом и ресурсами, такими как изображения и фильмы. Я использую zlib, чтобы открыть zip-файл в памяти, а затем перейти к отображению указанных ресурсов.Обнаружение типа mime-in-памяти с помощью Cocoa (OS X)?

Одна проблема, с которой я столкнулся, заключается в том, что я не могу правильно отображать видео, по-видимому, потому что QTMovie не может определить тип mime. Фильм, загруженный из файла ([QTMovie movieWithFile]) работает отлично. Загруженный из памяти ([QTMovie movieWithData]) отказывается работать.

Это имеет смысл, поскольку отсутствует расширение файла, QTMovie не может определить информацию типа mime. После недолгого поиска, я прибегал к использованию QTDataReference в следующем mannner:

NSData *movieData = ...read from memory...; 
QTDataReference *movieDataReference = [[QTDataReference alloc] initWithReferenceToData:movieData name:fileName MIMEType:@"video/x-m4v"]; 
QTMovie *mov = [QTMovie movieWithDataReference:movieDataReference error:&err]; 

Это прекрасно работает, однако жестко прописывать MIMETYPE далеко от идеала. У меня есть доступ к имени файла и расширению, поэтому я попытался найти мим-тип с помощью ИМПА (благодаря хорошим людям на #macdev):

- (NSString*)mimeTypeForExtension:(NSString*)ext { 

    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,(CFStringRef)ext,NULL); 
    return NSMakeCollectable(UTTypeCopyPreferredTagWithClass((CFStringRef)UTI,kUTTagClassMIMEType)); 
} 

Это, однако, не работает. Очевидно, что есть внутренняя база данных OS X расширений и соответствующих mime-типов. В противном случае фильмы с диска не будут работать. Как мне получить доступ к нему?

Спасибо!

+1

Только в случае, если кто-то борется с этим в будущем (как я) и хочет более гибкое решение: Я разработал [ `MagicKit.framework`] (https://github.com/ aidansteele/MagicKit) как (очень тонкая) обертка вокруг `libmagic`. Это устраняет необходимость обращения ко всем крайним случаям явно. – 2010-12-12 01:52:36

ответ

8

Проблема, связанная с тем, что у m4v и m4p нет типов mime, зарегистрированных в Launch Services (вероятно, из-за того, что тип mime для m4v и m4p не является стандартным). В любом случае то, что вы, вероятно, должны делать, это обработать крайние случаи, подобные этому, а затем проверить нуль при возврате функции (в случае, если расширение не зарегистрировано и не обрабатывается вами).

Другое дело в том, что вы пропускаете память с помощью вашего текущего использования. Я предполагаю, что вы используете сбор мусора, но первый вызов создает CFString, который никогда не выпускается. Вот предлагаемая реализация вашего метода:

-(NSString*)mimeTypeForExtension:(NSString*)ext 
{ 
    NSAssert(ext, @"Extension cannot be nil"); 
    NSString* mimeType = nil; 

    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 
     (CFStringRef)ext, NULL); 
    if(!UTI) return nil; 

    CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType); 
    if(!registeredType) // check for edge case 
    { 
     if([ext isEqualToString:@"m4v"]) 
      mimeType = @"video/x-m4v"; 
     else if([ext isEqualToString:@"m4p"]) 
      mimeType = @"audio/x-m4p"; 
     // handle anything else here that you know is not registered 
    } else { 
     mimeType = NSMakeCollectable(registeredType); 
    } 

    CFRelease(UTI); 
    return mimeType; 
} 
+0

Спасибо, Джейсон, ты прямо! – EightyEight 2008-11-20 00:15:22

1

Предлагайте людям изменить возврат к [mimeType autorelease]; - некоторые из нас по-прежнему используют древние пути!

И спасибо! Это было большой помощью.

5

Вы можете использовать NSWorkspace, чтобы система считала UTI файла.

-(NSString *)mimeTypeForFileAtPath:(NSString *)path error:(NSError **)err { 
    NSString *uti, *mimeType = nil; 

    if (!(uti = [[NSWorkspace sharedWorkspace] typeOfFile:path error:err])) 
    return nil; 
    if (err) 
    *err = nil; 

    if ((mimeType = (NSString *)UTTypeCopyPreferredTagWithClass((CFStringRef)uti, kUTTagClassMIMEType))) 
    mimeType = NSMakeCollectable(mimeType); 

    return mimeType; 
} 
+0

Это лучший ответ. – Shmidt 2015-12-04 00:20:17

 Смежные вопросы

  • Нет связанных вопросов^_^