Подтвердить что ты не робот

Как вы можете читать файлы MIME-типа в objective-c

Я заинтересован в обнаружении MIME-типа для файла в каталоге документов моего приложения iPhone. Поиск в документах не дал никаких ответов.

4b9b3361

Ответ 1

Это немного взломанный, но он должен работать, не знаю точно, потому что я просто догадываюсь об этом

Есть два варианта:

  • Если вам нужен только MIME-тип, используйте timeoutInterval: NSURLRequest.
  • Если вам нужны данные, вы должны использовать запрошенное NSURLRequest.

Обязательно выполняйте запрос в потоке, хотя он синхронный.

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

Ответ 2

Добавьте инфраструктуру 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);

Swift:

  import MobileCoreServices
  private func MIMEType(fileExtension: String) -> String? {
      if !fileExtension.isEmpty {            
        let UTIRef = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, nil)
        let UTI = UTIRef.takeUnretainedValue()
        UTIRef.release()

        let MIMETypeRef = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType)
        if MIMETypeRef != nil
        {
            let MIMEType = MIMETypeRef.takeUnretainedValue()
            MIMETypeRef.release()
            return MIMEType as String
        }
      }
      return nil
  }

Ответ 3

Принятый ответ проблематичен для больших файлов, как упомянули другие. Мое приложение имеет дело с видеофайлами, и загрузка всего видеофайла в память - хороший способ сделать iOS исчерпанной. Лучший способ сделать это можно найти здесь:

fooobar.com/questions/212970/...

Код сверху ссылки:

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

Ответ 4

Я использовал ответ, предоставленный slf в приложении cocoa (а не iPhone), и заметил, что URL-запрос, кажется, читает весь файл с диска, чтобы определить тип mime (не подходит для больших файлов).

Для тех, кто хочет сделать это на рабочем столе, приведен фрагмент, который я использовал (на основе предложения Луи):

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

На основе ответа Лоуренса Дол /slf выше, я решил, что 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

Решение Prcela не работает в Swift 2. Следующая упрощенная функция вернет тип mime для данного расширения файла в Swift 2:

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
}

Ответ 7

В Mac OS X это будет обрабатываться через LaunchServices и UTI. На iPhone они недоступны. Поскольку единственный способ доступа данных к вашей песочнице - для вас, вы можете ее разместить там, большинство приложений обладают внутренними знаниями о данных любого файла, который они могут читать.

Если вам нужна такая функция, вы должны файл запросить функцию с Apple.

Ответ 8

Я не уверен, что такое практика на iPhone, но если вам разрешено, я бы использовал философию UNIX здесь: используйте программу file, которая является стандартным способом обнаружения типа файла в UNIX операционная система. Он включает в себя обширную базу данных магических маркеров для обнаружения файлов. Поскольку file, вероятно, не отправлен на iPhone, вы можете включить его в свой пакет приложений. Может быть библиотека, реализующая функциональность file.

В качестве альтернативы вы можете доверять браузеру. Браузеры отправляют тип MIME, о котором они догадывались где-то в заголовках HTTP. Я знаю, что я могу легко получить информацию типа MIME в PHP. Это, конечно, зависит от того, хотите ли вы доверять клиенту.