¿Cómo se puede leer un archivo de tipo MIME en objective-c


Estoy interesado en detectar el tipo MIME de un archivo en el directorio documentos de mi aplicación iPhone. Una búsqueda a través de los documentos no dio ninguna respuesta.

Author: coneybeare, 2009-09-01

8 answers

Es un poco hackeado, pero debería funcionar, no lo sé con seguridad porque solo estoy adivinando

Hay dos opciones:

  1. Si solo necesita el tipo MIME, use el timeoutInterval: NSURLRequest.
  2. Si también desea los datos, debe usar el NSURLRequest comentado.

Asegúrese de realizar la solicitud en un subproceso, ya que es sincrónico.

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];
 54
Author: slf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-08 19:13:39

Add MobileCoreServices framework.

Objetivo 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

}

 36
Author: Prcela,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-30 15:09:51

La respuesta aceptada es problemática para archivos grandes, como otros han mencionado. Mi aplicación se ocupa de los archivos de vídeo, y cargar un archivo de vídeo completo en la memoria es una buena manera de hacer que iOS se quede sin memoria. Una mejor manera de hacer esto se puede encontrar aquí:

Https://stackoverflow.com/a/5998683/1864774

Código de arriba enlace:

+ (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];
}
 10
Author: Adam Lockhart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:43

La solución Prcela no funcionó en Swift 2. La siguiente función simplificada devolverá el tipo mime para una extensión de archivo dada en 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
}
 6
Author: dreamlab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:13

Estaba usando la respuesta proporcionada por slf en una aplicación cocoa (no iPhone) y noté que la solicitud de URL parece estar leyendo todo el archivo desde el disco para determinar el tipo mime (no es ideal para archivos grandes).

Para cualquiera que quiera hacer esto en el escritorio, aquí está el fragmento que usé (basado en la sugerencia de 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;
}

Si llamaras eso en un archivo PDF, escupiría: application / pdf

 5
Author: danw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-03 04:38:35

Basado en la respuesta de Lawrence Dol/slf anterior, he resuelto el problema de la NSURL cargando todo el archivo en la memoria cortando los primeros bytes en un trozo de cabeza y obteniendo el tipo Mime de eso. No lo he comparado, pero probablemente es más rápido de esta manera también.

+ (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;
}
 4
Author: got nate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:03:09

En Mac OS X esto se manejaría a través de LaunchServices y UTIs. En el iPhone no están disponibles. Dado que la única forma de que los datos ingresen a su sandbox es que los coloque allí, la mayoría de las aplicaciones tienen un conocimiento intrínseco sobre los datos de cualquier archivo que puedan leer.

Si necesita una característica de este tipo, debe presentar una solicitud de característica con Apple.

 1
Author: Louis Gerbarg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-01 22:17:10

No estoy seguro de cuáles son las prácticas en iPhone, pero si se le permite, haría uso de la filosofía UNIX aquí: use program file, que es la forma estándar de detectar el tipo de archivo en un sistema operativo UNIX. Incluye una amplia base de datos de marcadores mágicos para la detección de tipos de archivo. Dado que file probablemente no se incluye en el iPhone, podría incluirlo en su paquete de aplicaciones. Puede haber una biblioteca implementando la funcionalidad de file.

Alternativamente, puede confiar en el navegador. Navegadores enviar el tipo MIME que adivinaron en algún lugar de las cabeceras HTTP. Sé que puedo agarrar fácilmente la información del tipo MIME en PHP. Eso, por supuesto, depende de si estás dispuesto a confiar en el cliente.

 0
Author: Ivan Vučica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-09 18:25:21