【问题标题】:Determine MIME type from NSData?从 NSData 确定 MIME 类型?
【发布时间】:2014-03-14 10:17:15
【问题描述】:

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

我想知道是否可以从 NSData 中分辨出 mime 类型。这个问题只有几个答案,最近一个是 2010 年(4 年前!)。谢谢!

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

【问题讨论】:

  • 您可以有另一个字段来声明 MIME 类型并同时发送。
  • 没有(准确的)方法可以从数据本身确定数据的 MIME 类型。充其量你可以做出有根据的猜测。
  • 如果你想添加额外的 MIME 类型,你可以在这里找到它们的十六进制值:en.wikipedia.org/wiki/List_of_file_signatures

标签: ios objective-c mime-types nsdata


【解决方案1】:

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

对象:

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

斯威夫特:

static func mimeType(for data: Data) -> String {

    var b: UInt8 = 0
    data.copyBytes(to: &b, count: 1)

    switch b {
    case 0xFF:
        return "image/jpeg"
    case 0x89:
        return "image/png"
    case 0x47:
        return "image/gif"
    case 0x4D, 0x49:
        return "image/tiff"
    case 0x25:
        return "application/pdf"
    case 0xD0:
        return "application/vnd"
    case 0x46:
        return "text/plain"
    default:
        return "application/octet-stream"
    }
}

这仅处理主要文件类型,但您可以根据需要完成它:所有文件签名都可用here,只需使用与我相同的模式即可。

PS:所有对应的mime类型都可用here

【讨论】:

  • 嘿@blee908,这可能是一个有效的答案,你怎么看? :)
  • 我们如何检测音频文件?
  • @Ankush 检查上面提到的签名列表en.wikipedia.org/wiki/List_of_file_signatures
  • 然后找到您要检测的音频文件类型以及每种文件类型的案例。示例:根据文件签名数组,WMA第一个字节为0x30,所以添加case 0x30:return @"audio/x-ms-wma";休息;
  • 这会返回很多误报。
【解决方案2】:

❤️ 斯威夫特

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"
    }
}

【讨论】:

  • 完美运行
  • 可以设置doc或ppt文件的类型吗?
  • 这会返回很多误报。
【解决方案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 在他的回答中所说,这可能会变得棘手,具体取决于您要处理的内容。

编辑...

当然,第二种解决方案依赖于您显然没有的文件扩展名,但我相信您已经注意到了。

【讨论】:

  • 感谢您的反馈!
【解决方案4】:

既然您说您正在上传此数据,您应该已经知道 MIME 类型。您创建了数据对象,知道数据的来源,并且 MIME 类型的数量有限。因此,请使用适用于您的数据的任何一个。对于图像,它可能是image/jpegimage/png。对于视频,有很多 video/ 类型。您可以在 Mac 上的/etc/apache2/mime.types 中找到一长串 MIME 类型字符串。您需要其中的一个或多个,具体取决于您拥有的视频类型。

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

【讨论】:

  • 感谢您的解释。好吧,背景故事有点复杂。我正在编写一个 API 调用,但我不知道用户传入了什么。我只知道它是一个 NSData 类,它可以是图像或视频。而且我也需要 MIME 类型通过 AFNetworking 正确上传文件。
  • 您的服务器是否需要知道确切的 MIME 类型?您可以随时使用application/octet-stream 来表示“某种二进制数据”。如果您需要更具体的内容,最好的方法可能是将其加载到 AVFoundation 类(可能是 AVAsset)中,然后查看元数据以选择 MIME 类型。
  • 非常接近。事实证明,“application/octet-stream”似乎可以工作(我测试了 png 和 jpeg,但输入了相同的 MIME 类型),但是 AFNetworking 需要知道文件扩展名,所以你需要传入一个 NSString *filename “mypic.jpeg”或“mypic.png”不是“mypic”
  • 好的,好吧,我不使用AFNetworking,所以我不知道。虽然它是开源的,所以更改它始终是一种选择。
猜你喜欢
  • 2011-08-25
  • 2011-07-15
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 2012-09-10
相关资源
最近更新 更多