2014-02-14 81 views
14

如何确定NSData对象的MIME类型?我计划让用户从iPhone上传视频/图片,并将该文件包装在NSData类中。从NSData确定MIME类型?

我想知道是否可以告诉NSData的MIME类型。这个问题只有几个答案,最近的一个是2010年(4年前!)。谢谢!

NSData *data; // can be an image or video 
NSString *mimeType = [data getMimetype]; // how would I implement getMimeType 
+0

你可以hav另一个字段声明MIME类型并将其发送。 – aust

+0

没有(准确的)方式从数据本身确定数据的MIME类型。充其量你可以做出有根据的猜测。 –

+0

如果你想添加额外的MIME类型,你可以在这里找到他们的十六进制值:https://en.wikipedia.org/wiki/List_of_file_signatures –

回答

2

既然你说你上传这个数据,你应该已经知道的MIME类型。您创建了数据对象,您知道数据来自哪里,并且MIME类型的数量有限。因此,请使用适用于您的数据的内容。对于图像来说,它可能是image/jpegimage/png。对于视频,有一些video/类型。您可以在/etc/apache2/mime.types的Mac上找到一长串MIME类型字符串。您需要一种或多种视您使用的视频类型而定。

确定MIME类型是一个棘手的问题;一个NSData可以编码任何种类的二进制数据。确定编码的唯一方法是检查字节。这反过来意味着了解什么字节流存在于不同的文件类型中。应该可以在许多(但不是全部)情况下使用查找字典,并且可能存在用于常见文件类型的某处的开源实现。要了解所涉及的内容,请在Mac上尝试man file,并在/usr/share/file/magic/中查看各种文件类型是如何识别的(file命令不会生成MIME类型,但它会分析文件内容以尝试识别文件类型,因此它是原理相同)。

+0

感谢您的解释。那么,背景故事有点复杂。我正在编写一个API调用,我不知道用户通过了什么。我所知道的是它的一个NSData类,它可以是图像或视频。我需要MIME类型,通过AFNetworking正确地上传文件。 – blee908

+0

您的服务器是否需要知道确切的MIME类型?你总是可以回退'application/octet-stream'来表示“某种二进制数据”。如果你需要更具体的东西,最好的方法是将它加载到一个'AVFoundation'类(也许'AVAsset'),然后查看元数据以选择一个MIME类型。 –

+0

非常接近。事实证明,“应用程序/八位字节流”似乎工作(我测试了PNG和JPEG,但输入相同的MIME类型),但AFNetworking需要知道文件扩展名,所以你需要传递一个NSString *文件名“mypic.jpeg”或“mypic.png”不是“mypic” – blee908

3

据我所知,NSData是只是包装了一个字节数组的数据对象:

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html

...所以我能想到的,如果你想发现它的MIME类型的一种方式是检查字节本身,然后从那里猜测类型。这里有一个例子:Finding image type from NSData or UIImage

我也发现这个:Determine MIME Type of NSData Loaded From a File;这是指一些内部数据库(我猜)可以用于MIME类型的查找。

但就像Tom Harrington在他的回答中所说的那样,根据你所处理的情况可能会变得棘手。

编辑...

当然,这第二个解决方案依赖于文件扩展名,你显然没有,但我敢肯定你是否注意到了。

+0

感谢您的反馈! – blee908

24

基于ml's answer from a similar post,我已经添加了MIME类型确定为NSData的:

+ (NSString *)mimeTypeForData:(NSData *)data { 
    uint8_t c; 
    [data getBytes:&c length:1]; 

    switch (c) { 
     case 0xFF: 
      return @"image/jpeg"; 
      break; 
     case 0x89: 
      return @"image/png"; 
      break; 
     case 0x47: 
      return @"image/gif"; 
      break; 
     case 0x49: 
     case 0x4D: 
      return @"image/tiff"; 
      break; 
     case 0x25: 
      return @"application/pdf"; 
      break; 
     case 0xD0: 
      return @"application/vnd"; 
      break; 
     case 0x46: 
      return @"text/plain"; 
      break; 
     default: 
      return @"application/octet-stream"; 
    } 
    return nil; 
} 

这仅处理主要文件类型,但你可以完成它:你能找到的所有文件的签名here,只是使用和我一样。

PS:所有相应的mime类型可here

+0

嘿@ blee908,这可能是一个有效的答案,你怎么看? :) – Tib

+0

我们如何检测音频文件? – Ankush

+0

@Ankush检查上面提到的签名列表https://en.wikipedia.org/wiki/List_of_file_signatures – Tib

10

❤️夫特

extension Data { 
    private static let mimeTypeSignatures: [UInt8 : String] = [ 
     0xFF : "image/jpeg", 
     0x89 : "image/png", 
     0x47 : "image/gif", 
     0x49 : "image/tiff", 
     0x4D : "image/tiff", 
     0x25 : "application/pdf", 
     0xD0 : "application/vnd", 
     0x46 : "text/plain", 
     ] 

    var mimeType: String { 
     var c: UInt8 = 0 
     copyBytes(to: &c, count: 1) 
     return Data.mimeTypeSignatures[c] ?? "application/octet-stream" 
    } 
} 
+0

真棒,它工作完美! – kikettas

0

VAR值= [UINT8](重复:0,计数:imgData.count)

imgData .copyBytes(至:&值,计数:1)

switch values { 
    case 0xff: 
     return "image/jpeg" 
    case 0x89: 
     return "image/png" 
    case 0x47: 
     return "image/gif" 
    case 0x49, 0x4d: 
     return "image/tiff" 
    } 

    return ""