2014-02-14 79 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 ""