Определить тип MIME из NSData?

Как вы определяете тип mime для объекта NSData? Я планирую, чтобы пользователь загрузил видео/картинку со своего iPhone и включил этот файл в класс NSData.

Мне было интересно, могу ли я указать тип mime из NSData. На этот вопрос есть только несколько ответов, а самый последний - с 2010 года (4 года назад!). Спасибо!

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

Ответ 1

На основе мл ответа из аналогичного поста я добавил определение типов пантомимы для NSData:

ObjC:

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

Swift:

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

Это относится только к основным типам файлов, но вы можете выполнить его в соответствии с вашими потребностями: здесь доступны все подписи файлов, просто используйте тот же шаблон, что и я.

PS: все соответствующие типы пантомимы доступны здесь

Ответ 2

❤️ Swift

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

Ответ 3

Насколько я знаю, NSData - это просто объект данных, который обертывает массив байтов:

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

... поэтому одним из способов, о котором я могу думать, если вы хотите открыть его тип MIME, является проверка самих байтов, а затем догадываться о типе оттуда. Вот пример этого здесь: Поиск типа изображения из NSData или UIImage

Я также нашел это: Определить тип MIME NSData, загруженный из файла; который относится к некоторой внутренней базе данных (я думаю), которая может использоваться для поиска типа MIME.

Но, как говорит Том Харрингтон в своем ответе, это может стать сложным в зависимости от того, с чем вы имеете дело.

Изменить...

Конечно, это второе решение зависит от расширения файла, которого вы, очевидно, не имеете, но я уверен, что вы это уже заметили.

Ответ 4

Поскольку вы говорите, что вы загружаете эти данные, вы уже должны знать тип MIME. Вы создали объект данных, вы знаете, откуда пришли данные, и существует ограниченное количество типов MIME. Поэтому используйте то, что применимо к вашим данным. Для изображения это возможно image/jpeg или image/png. Для видео есть группа типов video/. Вы можете найти длинный список строк типа MIME на вашем Mac в /etc/apache2/mime.types. Вы хотите, чтобы один или несколько из них зависели от того, какое видео вы имеете.

Определение типа MIME является липкой проблемой; a NSData может кодировать любые двоичные данные. Единственный способ определить, что было закодировано, - это изучить байты. Это, в свою очередь, означает некоторое понимание того, какие потоки байтов существуют в разных типах файлов. Должно быть возможно использовать словарь поиска во многих (но не во всех) случаях, и может существовать реализация с открытым исходным кодом где-то для общих типов файлов. Чтобы получить представление о том, что задействовано, попробуйте man file на вашем Mac и посмотрите /usr/share/file/magic/, чтобы узнать, как идентифицируются различные типы файлов (команда file не создает типы MIME, но она анализирует содержимое файла, чтобы попытаться идентифицировать типы файлов, так что это тот же принцип).

Ответ 5

var values = [UInt8](repeating:0, count:imgData.count) 
imgData.copyBytes(to: &values, count: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 ""

Ответ 6

Решение Swifty, основанное на принятом ответе:

import Foundation

extension Data {
    var mimeType: String {
        var byte: UInt8 = 0
        copyBytes(to: &byte, count: 1)

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

Использование:

data.mimeType