2008-09-12 79 views

回答

67

在Urlmon.dll中,有一个叫做的函数。

从文档

MIME类型检测,或“数据嗅探”是指确定来自二进制数据的适当的MIME类型的过程。最终结果取决于服务器提供的MIME类型标头,文件扩展名和/或数据本身的组合。通常,只有前256个字节的数据是重要的。

因此,请从文件中读取第一个(最多)256个字节并将其传递到。

+5

这种方法有多可靠? – 2009-05-16 00:56:52

+17

根据http://stackoverflow.com/questions/4833113/why-does-the-findmimefromdata-function-from-urlmon-dll-return-mime-type-applicat,该函数能够确定只有26种类型,所以我不认为这是可靠的。例如。 '* .docx'文件被确定为'application/x-zip-compressed'。 – Monsignor 2011-02-11 04:20:30

+50

我想这是因为docx表面上是一个zip文件。 – 2011-04-06 23:42:09

160

我在最后使用了urlmon.dll。我认为会有一个更简单的方法,但这是有效的。我包含代码来帮助其他人,并让我再次找到它,如果我需要它。

using System.Runtime.InteropServices; 

...

[DllImport(@"urlmon.dll", CharSet = CharSet.Auto)] 
    private extern static System.UInt32 FindMimeFromData(
     System.UInt32 pBC, 
     [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, 
     System.UInt32 cbSize, 
     [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed, 
     System.UInt32 dwMimeFlags, 
     out System.UInt32 ppwzMimeOut, 
     System.UInt32 dwReserverd 
    ); 

    public static string getMimeFromFile(string filename) 
    { 
     if (!File.Exists(filename)) 
      throw new FileNotFoundException(filename + " not found"); 

     byte[] buffer = new byte[256]; 
     using (FileStream fs = new FileStream(filename, FileMode.Open)) 
     { 
      if (fs.Length >= 256) 
       fs.Read(buffer, 0, 256); 
      else 
       fs.Read(buffer, 0, (int)fs.Length); 
     } 
     try 
     { 
      System.UInt32 mimetype; 
      FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0); 
      System.IntPtr mimeTypePtr = new IntPtr(mimetype); 
      string mime = Marshal.PtrToStringUni(mimeTypePtr); 
      Marshal.FreeCoTaskMem(mimeTypePtr); 
      return mime; 
     } 
     catch (Exception e) 
     { 
      return "unknown/unknown"; 
     } 
    } 
+0

这有多可靠? – 2009-09-17 14:30:38

+0

,或者更确切地说,支持哪些MIME类型? – flq 2010-03-14 10:09:21

+3

可能是在注册表中映射的任何东西。 – mkmurray 2010-05-20 17:01:37

28

您还可以在注册表中。

using System.IO; 
    using Microsoft.Win32; 

    string GetMimeType(FileInfo fileInfo) 
    { 
     string mimeType = "application/unknown"; 

     RegistryKey regKey = Registry.ClassesRoot.OpenSubKey(
      fileInfo.Extension.ToLower() 
      ); 

     if(regKey != null) 
     { 
      object contentType = regKey.GetValue("Content Type"); 

      if(contentType != null) 
       mimeType = contentType.ToString(); 
     } 

     return mimeType; 
    } 

这种或那种方式你将不得不进军MIME的数据库 - 无论他们是从扩展或幻数映射是有点微不足道 - windows的注册表是一个这样的地方。 对于独立于平台的解决方案,虽然人们不得不将这个DB与代码一起发运(或作为独立库)。

3

我认为正确的答案是史蒂夫摩根和塞尔盖的答案的结合。这就是Internet Explorer的功能。对的拨打电话仅适用于26种硬编码的MIME类型。此外,即使可能存在更具体,更适当的MIME类型,它也会给出不明确的MIME类型(如text/plainapplication/octet-stream)。如果它没有给出一个好的MIME类型,你可以到注册表中寻找更具体的MIME类型。服务器注册表可能有更多最新的MIME类型。

参考:http://msdn.microsoft.com/en-us/library/ms775147(VS.85).aspx

104

我发现一个硬编码的解决方案,我希望我可以帮助别人:

public static class MIMEAssistant 
{ 
    private static readonly Dictionary<string, string> MIMETypesDictionary = new Dictionary<string, string> 
    { 
    {"ai", "application/postscript"}, 
    {"aif", "audio/x-aiff"}, 
    {"aifc", "audio/x-aiff"}, 
    {"aiff", "audio/x-aiff"}, 
    {"asc", "text/plain"}, 
    {"atom", "application/atom+xml"}, 
    {"au", "audio/basic"}, 
    {"avi", "video/x-msvideo"}, 
    {"bcpio", "application/x-bcpio"}, 
    {"bin", "application/octet-stream"}, 
    {"bmp", "image/bmp"}, 
    {"cdf", "application/x-netcdf"}, 
    {"cgm", "image/cgm"}, 
    {"class", "application/octet-stream"}, 
    {"cpio", "application/x-cpio"}, 
    {"cpt", "application/mac-compactpro"}, 
    {"csh", "application/x-csh"}, 
    {"css", "text/css"}, 
    {"dcr", "application/x-director"}, 
    {"dif", "video/x-dv"}, 
    {"dir", "application/x-director"}, 
    {"djv", "image/vnd.djvu"}, 
    {"djvu", "image/vnd.djvu"}, 
    {"dll", "application/octet-stream"}, 
    {"dmg", "application/octet-stream"}, 
    {"dms", "application/octet-stream"}, 
    {"doc", "application/msword"}, 
    {"docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, 
    {"dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, 
    {"docm","application/vnd.ms-word.document.macroEnabled.12"}, 
    {"dotm","application/vnd.ms-word.template.macroEnabled.12"}, 
    {"dtd", "application/xml-dtd"}, 
    {"dv", "video/x-dv"}, 
    {"dvi", "application/x-dvi"}, 
    {"dxr", "application/x-director"}, 
    {"eps", "application/postscript"}, 
    {"etx", "text/x-setext"}, 
    {"exe", "application/octet-stream"}, 
    {"ez", "application/andrew-inset"}, 
    {"gif", "image/gif"}, 
    {"gram", "application/srgs"}, 
    {"grxml", "application/srgs+xml"}, 
    {"gtar", "application/x-gtar"}, 
    {"hdf", "application/x-hdf"}, 
    {"hqx", "application/mac-binhex40"}, 
    {"htm", "text/html"}, 
    {"html", "text/html"}, 
    {"ice", "x-conference/x-cooltalk"}, 
    {"ico", "image/x-icon"}, 
    {"ics", "text/calendar"}, 
    {"ief", "image/ief"}, 
    {"ifb", "text/calendar"}, 
    {"iges", "model/iges"}, 
    {"igs", "model/iges"}, 
    {"jnlp", "application/x-java-jnlp-file"}, 
    {"jp2", "image/jp2"}, 
    {"jpe", "image/jpeg"}, 
    {"jpeg", "image/jpeg"}, 
    {"jpg", "image/jpeg"}, 
    {"js", "application/x-javascript"}, 
    {"kar", "audio/midi"}, 
    {"latex", "application/x-latex"}, 
    {"lha", "application/octet-stream"}, 
    {"lzh", "application/octet-stream"}, 
    {"m3u", "audio/x-mpegurl"}, 
    {"m4a", "audio/mp4a-latm"}, 
    {"m4b", "audio/mp4a-latm"}, 
    {"m4p", "audio/mp4a-latm"}, 
    {"m4u", "video/vnd.mpegurl"}, 
    {"m4v", "video/x-m4v"}, 
    {"mac", "image/x-macpaint"}, 
    {"man", "application/x-troff-man"}, 
    {"mathml", "application/mathml+xml"}, 
    {"me", "application/x-troff-me"}, 
    {"mesh", "model/mesh"}, 
    {"mid", "audio/midi"}, 
    {"midi", "audio/midi"}, 
    {"mif", "application/vnd.mif"}, 
    {"mov", "video/quicktime"}, 
    {"movie", "video/x-sgi-movie"}, 
    {"mp2", "audio/mpeg"}, 
    {"mp3", "audio/mpeg"}, 
    {"mp4", "video/mp4"}, 
    {"mpe", "video/mpeg"}, 
    {"mpeg", "video/mpeg"}, 
    {"mpg", "video/mpeg"}, 
    {"mpga", "audio/mpeg"}, 
    {"ms", "application/x-troff-ms"}, 
    {"msh", "model/mesh"}, 
    {"mxu", "video/vnd.mpegurl"}, 
    {"nc", "application/x-netcdf"}, 
    {"oda", "application/oda"}, 
    {"ogg", "application/ogg"}, 
    {"pbm", "image/x-portable-bitmap"}, 
    {"pct", "image/pict"}, 
    {"pdb", "chemical/x-pdb"}, 
    {"pdf", "application/pdf"}, 
    {"pgm", "image/x-portable-graymap"}, 
    {"pgn", "application/x-chess-pgn"}, 
    {"pic", "image/pict"}, 
    {"pict", "image/pict"}, 
    {"png", "image/png"}, 
    {"pnm", "image/x-portable-anymap"}, 
    {"pnt", "image/x-macpaint"}, 
    {"pntg", "image/x-macpaint"}, 
    {"ppm", "image/x-portable-pixmap"}, 
    {"ppt", "application/vnd.ms-powerpoint"}, 
    {"pptx","application/vnd.openxmlformats-officedocument.presentationml.presentation"}, 
    {"potx","application/vnd.openxmlformats-officedocument.presentationml.template"}, 
    {"ppsx","application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, 
    {"ppam","application/vnd.ms-powerpoint.addin.macroEnabled.12"}, 
    {"pptm","application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, 
    {"potm","application/vnd.ms-powerpoint.template.macroEnabled.12"}, 
    {"ppsm","application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, 
    {"ps", "application/postscript"}, 
    {"qt", "video/quicktime"}, 
    {"qti", "image/x-quicktime"}, 
    {"qtif", "image/x-quicktime"}, 
    {"ra", "audio/x-pn-realaudio"}, 
    {"ram", "audio/x-pn-realaudio"}, 
    {"ras", "image/x-cmu-raster"}, 
    {"rdf", "application/rdf+xml"}, 
    {"rgb", "image/x-rgb"}, 
    {"rm", "application/vnd.rn-realmedia"}, 
    {"roff", "application/x-troff"}, 
    {"rtf", "text/rtf"}, 
    {"rtx", "text/richtext"}, 
    {"sgm", "text/sgml"}, 
    {"sgml", "text/sgml"}, 
    {"sh", "application/x-sh"}, 
    {"shar", "application/x-shar"}, 
    {"silo", "model/mesh"}, 
    {"sit", "application/x-stuffit"}, 
    {"skd", "application/x-koan"}, 
    {"skm", "application/x-koan"}, 
    {"skp", "application/x-koan"}, 
    {"skt", "application/x-koan"}, 
    {"smi", "application/smil"}, 
    {"smil", "application/smil"}, 
    {"snd", "audio/basic"}, 
    {"so", "application/octet-stream"}, 
    {"spl", "application/x-futuresplash"}, 
    {"src", "application/x-wais-source"}, 
    {"sv4cpio", "application/x-sv4cpio"}, 
    {"sv4crc", "application/x-sv4crc"}, 
    {"svg", "image/svg+xml"}, 
    {"swf", "application/x-shockwave-flash"}, 
    {"t", "application/x-troff"}, 
    {"tar", "application/x-tar"}, 
    {"tcl", "application/x-tcl"}, 
    {"tex", "application/x-tex"}, 
    {"texi", "application/x-texinfo"}, 
    {"texinfo", "application/x-texinfo"}, 
    {"tif", "image/tiff"}, 
    {"tiff", "image/tiff"}, 
    {"tr", "application/x-troff"}, 
    {"tsv", "text/tab-separated-values"}, 
    {"txt", "text/plain"}, 
    {"ustar", "application/x-ustar"}, 
    {"vcd", "application/x-cdlink"}, 
    {"vrml", "model/vrml"}, 
    {"vxml", "application/voicexml+xml"}, 
    {"wav", "audio/x-wav"}, 
    {"wbmp", "image/vnd.wap.wbmp"}, 
    {"wbmxl", "application/vnd.wap.wbxml"}, 
    {"wml", "text/vnd.wap.wml"}, 
    {"wmlc", "application/vnd.wap.wmlc"}, 
    {"wmls", "text/vnd.wap.wmlscript"}, 
    {"wmlsc", "application/vnd.wap.wmlscriptc"}, 
    {"wrl", "model/vrml"}, 
    {"xbm", "image/x-xbitmap"}, 
    {"xht", "application/xhtml+xml"}, 
    {"xhtml", "application/xhtml+xml"}, 
    {"xls", "application/vnd.ms-excel"},       
    {"xml", "application/xml"}, 
    {"xpm", "image/x-xpixmap"}, 
    {"xsl", "application/xml"}, 
    {"xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, 
    {"xltx","application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, 
    {"xlsm","application/vnd.ms-excel.sheet.macroEnabled.12"}, 
    {"xltm","application/vnd.ms-excel.template.macroEnabled.12"}, 
    {"xlam","application/vnd.ms-excel.addin.macroEnabled.12"}, 
    {"xlsb","application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, 
    {"xslt", "application/xslt+xml"}, 
    {"xul", "application/vnd.mozilla.xul+xml"}, 
    {"xwd", "image/x-xwindowdump"}, 
    {"xyz", "chemical/x-xyz"}, 
    {"zip", "application/zip"} 
    }; 

    public static string GetMIMEType(string fileName) 
    { 
    //get file extension 
    string extension = Path.GetExtension(fileName).ToLowerInvariant(); 

    if (extension.Length > 0 && 
     MIMETypesDictionary.ContainsKey(extension.Remove(0, 1))) 
    { 
     return MIMETypesDictionary[extension.Remove(0, 1)]; 
    } 
    return "unknown/unknown"; 
    } 
} 
+42

但这是基于文件名。对于某人而言,这可能是有用的,而不是OP,他希望通过文件内容来完成。 – mandreko 2011-08-23 18:09:28

+3

此列表的子集还方便将WebImage.ImageFormat映射回MIME类型。谢谢! – Derrick 2011-08-29 17:33:33

+0

@Rabbi ...当他们投票! – 2012-03-30 07:22:50

3

我发现这是有用的。 对于VB.NET开发者:

Public Shared Function GetFromFileName(ByVal fileName As String) As String 
     Return GetFromExtension(Path.GetExtension(fileName).Remove(0, 1)) 
    End Function 

    Public Shared Function GetFromExtension(ByVal extension As String) As String 
     If extension.StartsWith("."c) Then 
      extension = extension.Remove(0, 1) 
     End If 

     If MIMETypesDictionary.ContainsKey(extension) Then 
      Return MIMETypesDictionary(extension) 
     End If 

     Return "unknown/unknown" 
    End Function 

    Private Shared ReadOnly MIMETypesDictionary As New Dictionary(Of String, String)() From { _ 
     {"ai", "application/postscript"}, _ 
     {"aif", "audio/x-aiff"}, _ 
     {"aifc", "audio/x-aiff"}, _ 
     {"aiff", "audio/x-aiff"}, _ 
     {"asc", "text/plain"}, _ 
     {"atom", "application/atom+xml"}, _ 
     {"au", "audio/basic"}, _ 
     {"avi", "video/x-msvideo"}, _ 
     {"bcpio", "application/x-bcpio"}, _ 
     {"bin", "application/octet-stream"}, _ 
     {"bmp", "image/bmp"}, _ 
     {"cdf", "application/x-netcdf"}, _ 
     {"cgm", "image/cgm"}, _ 
     {"class", "application/octet-stream"}, _ 
     {"cpio", "application/x-cpio"}, _ 
     {"cpt", "application/mac-compactpro"}, _ 
     {"csh", "application/x-csh"}, _ 
     {"css", "text/css"}, _ 
     {"dcr", "application/x-director"}, _ 
     {"dif", "video/x-dv"}, _ 
     {"dir", "application/x-director"}, _ 
     {"djv", "image/vnd.djvu"}, _ 
     {"djvu", "image/vnd.djvu"}, _ 
     {"dll", "application/octet-stream"}, _ 
     {"dmg", "application/octet-stream"}, _ 
     {"dms", "application/octet-stream"}, _ 
     {"doc", "application/msword"}, _ 
     {"dtd", "application/xml-dtd"}, _ 
     {"dv", "video/x-dv"}, _ 
     {"dvi", "application/x-dvi"}, _ 
     {"dxr", "application/x-director"}, _ 
     {"eps", "application/postscript"}, _ 
     {"etx", "text/x-setext"}, _ 
     {"exe", "application/octet-stream"}, _ 
     {"ez", "application/andrew-inset"}, _ 
     {"gif", "image/gif"}, _ 
     {"gram", "application/srgs"}, _ 
     {"grxml", "application/srgs+xml"}, _ 
     {"gtar", "application/x-gtar"}, _ 
     {"hdf", "application/x-hdf"}, _ 
     {"hqx", "application/mac-binhex40"}, _ 
     {"htm", "text/html"}, _ 
     {"html", "text/html"}, _ 
     {"ice", "x-conference/x-cooltalk"}, _ 
     {"ico", "image/x-icon"}, _ 
     {"ics", "text/calendar"}, _ 
     {"ief", "image/ief"}, _ 
     {"ifb", "text/calendar"}, _ 
     {"iges", "model/iges"}, _ 
     {"igs", "model/iges"}, _ 
     {"jnlp", "application/x-java-jnlp-file"}, _ 
     {"jp2", "image/jp2"}, _ 
     {"jpe", "image/jpeg"}, _ 
     {"jpeg", "image/jpeg"}, _ 
     {"jpg", "image/jpeg"}, _ 
     {"js", "application/x-javascript"}, _ 
     {"kar", "audio/midi"}, _ 
     {"latex", "application/x-latex"}, _ 
     {"lha", "application/octet-stream"}, _ 
     {"lzh", "application/octet-stream"}, _ 
     {"m3u", "audio/x-mpegurl"}, _ 
     {"m4a", "audio/mp4a-latm"}, _ 
     {"m4b", "audio/mp4a-latm"}, _ 
     {"m4p", "audio/mp4a-latm"}, _ 
     {"m4u", "video/vnd.mpegurl"}, _ 
     {"m4v", "video/x-m4v"}, _ 
     {"mac", "image/x-macpaint"}, _ 
     {"man", "application/x-troff-man"}, _ 
     {"mathml", "application/mathml+xml"}, _ 
     {"me", "application/x-troff-me"}, _ 
     {"mesh", "model/mesh"}, _ 
     {"mid", "audio/midi"}, _ 
     {"midi", "audio/midi"}, _ 
     {"mif", "application/vnd.mif"}, _ 
     {"mov", "video/quicktime"}, _ 
     {"movie", "video/x-sgi-movie"}, _ 
     {"mp2", "audio/mpeg"}, _ 
     {"mp3", "audio/mpeg"}, _ 
     {"mp4", "video/mp4"}, _ 
     {"mpe", "video/mpeg"}, _ 
     {"mpeg", "video/mpeg"}, _ 
     {"mpg", "video/mpeg"}, _ 
     {"mpga", "audio/mpeg"}, _ 
     {"ms", "application/x-troff-ms"}, _ 
     {"msh", "model/mesh"}, _ 
     {"mxu", "video/vnd.mpegurl"}, _ 
     {"nc", "application/x-netcdf"}, _ 
     {"oda", "application/oda"}, _ 
     {"ogg", "application/ogg"}, _ 
     {"pbm", "image/x-portable-bitmap"}, _ 
     {"pct", "image/pict"}, _ 
     {"pdb", "chemical/x-pdb"}, _ 
     {"pdf", "application/pdf"}, _ 
     {"pgm", "image/x-portable-graymap"}, _ 
     {"pgn", "application/x-chess-pgn"}, _ 
     {"pic", "image/pict"}, _ 
     {"pict", "image/pict"}, _ 
     {"png", "image/png"}, _ 
     {"pnm", "image/x-portable-anymap"}, _ 
     {"pnt", "image/x-macpaint"}, _ 
     {"pntg", "image/x-macpaint"}, _ 
     {"ppm", "image/x-portable-pixmap"}, _ 
     {"ppt", "application/vnd.ms-powerpoint"}, _ 
     {"ps", "application/postscript"}, _ 
     {"qt", "video/quicktime"}, _ 
     {"qti", "image/x-quicktime"}, _ 
     {"qtif", "image/x-quicktime"}, _ 
     {"ra", "audio/x-pn-realaudio"}, _ 
     {"ram", "audio/x-pn-realaudio"}, _ 
     {"ras", "image/x-cmu-raster"}, _ 
     {"rdf", "application/rdf+xml"}, _ 
     {"rgb", "image/x-rgb"}, _ 
     {"rm", "application/vnd.rn-realmedia"}, _ 
     {"roff", "application/x-troff"}, _ 
     {"rtf", "text/rtf"}, _ 
     {"rtx", "text/richtext"}, _ 
     {"sgm", "text/sgml"}, _ 
     {"sgml", "text/sgml"}, _ 
     {"sh", "application/x-sh"}, _ 
     {"shar", "application/x-shar"}, _ 
     {"silo", "model/mesh"}, _ 
     {"sit", "application/x-stuffit"}, _ 
     {"skd", "application/x-koan"}, _ 
     {"skm", "application/x-koan"}, _ 
     {"skp", "application/x-koan"}, _ 
     {"skt", "application/x-koan"}, _ 
     {"smi", "application/smil"}, _ 
     {"smil", "application/smil"}, _ 
     {"snd", "audio/basic"}, _ 
     {"so", "application/octet-stream"}, _ 
     {"spl", "application/x-futuresplash"}, _ 
     {"src", "application/x-wais-source"}, _ 
     {"sv4cpio", "application/x-sv4cpio"}, _ 
     {"sv4crc", "application/x-sv4crc"}, _ 
     {"svg", "image/svg+xml"}, _ 
     {"swf", "application/x-shockwave-flash"}, _ 
     {"t", "application/x-troff"}, _ 
     {"tar", "application/x-tar"}, _ 
     {"tcl", "application/x-tcl"}, _ 
     {"tex", "application/x-tex"}, _ 
     {"texi", "application/x-texinfo"}, _ 
     {"texinfo", "application/x-texinfo"}, _ 
     {"tif", "image/tiff"}, _ 
     {"tiff", "image/tiff"}, _ 
     {"tr", "application/x-troff"}, _ 
     {"tsv", "text/tab-separated-values"}, _ 
     {"txt", "text/plain"}, _ 
     {"ustar", "application/x-ustar"}, _ 
     {"vcd", "application/x-cdlink"}, _ 
     {"vrml", "model/vrml"}, _ 
     {"vxml", "application/voicexml+xml"}, _ 
     {"wav", "audio/x-wav"}, _ 
     {"wbmp", "image/vnd.wap.wbmp"}, _ 
     {"wbmxl", "application/vnd.wap.wbxml"}, _ 
     {"wml", "text/vnd.wap.wml"}, _ 
     {"wmlc", "application/vnd.wap.wmlc"}, _ 
     {"wmls", "text/vnd.wap.wmlscript"}, _ 
     {"wmlsc", "application/vnd.wap.wmlscriptc"}, _ 
     {"wrl", "model/vrml"}, _ 
     {"xbm", "image/x-xbitmap"}, _ 
     {"xht", "application/xhtml+xml"}, _ 
     {"xhtml", "application/xhtml+xml"}, _ 
     {"xls", "application/vnd.ms-excel"}, _ 
     {"xml", "application/xml"}, _ 
     {"xpm", "image/x-xpixmap"}, _ 
     {"xsl", "application/xml"}, _ 
     {"xslt", "application/xslt+xml"}, _ 
     {"xul", "application/vnd.mozilla.xul+xml"}, _ 
     {"xwd", "image/x-xwindowdump"}, _ 
     {"xyz", "chemical/x-xyz"}, _ 
     {"zip", "application/zip"} _ 
     } 
+4

看起来可能是一个旧列表... no .docx,.xlsx等 – JoelFan 2012-01-24 19:56:59

2

我遇到了同样的问题,最终还是选择了我自己的柯克Baucom的解决方案,found here味道。

在我看来,这是一个有人写一个在线查找服务的机会。

无论如何,希望它有帮助。

9

我使用一个混合的解决方案:

using System.Runtime.InteropServices; 

    [DllImport (@"urlmon.dll", CharSet = CharSet.Auto)] 
    private extern static System.UInt32 FindMimeFromData(
     System.UInt32 pBC, 
     [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, 
     System.UInt32 cbSize, 
     [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed, 
     System.UInt32 dwMimeFlags, 
     out System.UInt32 ppwzMimeOut, 
     System.UInt32 dwReserverd 
    ); 

    private string GetMimeFromRegistry (string Filename) 
    { 
     string mime = "application/octetstream"; 
     string ext = System.IO.Path.GetExtension(Filename).ToLower(); 
     Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext); 
     if (rk != null && rk.GetValue("Content Type") != null) 
      mime = rk.GetValue("Content Type").ToString(); 
     return mime; 
    } 

    public string GetMimeTypeFromFileAndRegistry (string filename) 
    { 
     if (!File.Exists(filename)) 
     { 
      return GetMimeFromRegistry (filename); 
     } 

     byte[] buffer = new byte[256]; 

     using (FileStream fs = new FileStream(filename, FileMode.Open)) 
     { 
      if (fs.Length >= 256) 
       fs.Read(buffer, 0, 256); 
      else 
       fs.Read(buffer, 0, (int)fs.Length); 
     } 

     try 
     {    
      System.UInt32 mimetype; 

      FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0); 

      System.IntPtr mimeTypePtr = new IntPtr(mimetype); 

      string mime = Marshal.PtrToStringUni(mimeTypePtr); 

      Marshal.FreeCoTaskMem(mimeTypePtr); 

      if (string.IsNullOrWhiteSpace (mime) || 
       mime =="text/plain" || mime == "application/octet-stream")      
      { 
       return GetMimeFromRegistry (filename); 
      } 

      return mime; 
     } 
     catch (Exception e) 
     { 
      return GetMimeFromRegistry (filename); 
     } 
    } 
+1

感谢您的代码。它部分工作。对于“doc”和“tif”文件,它返回“application/octet-stream”。还有其他选择可以使用吗? – 2012-04-04 23:41:03

1

如果有人为它,他们可以端口优秀的Perl模块File::Type到.NET。在代码中是每个文件类型或正则表达式匹配的一组文件头幻数查找。

下面是一个.NET文件类型检测库http://filetypedetective.codeplex.com/,但它目前只检测少量的文件。

76

编辑:只要使用Mime Detective

我使用字节数组序列,以确定正确的MIME类型的给定的文件。通过查看文件名的文件扩展名,这一点的优点是,如果用户要重命名文件以绕过某些文件类型上传限制,则文件扩展名将无法捕捉到这一点。另一方面,通过字节数组获取文件签名将停止发生恶作剧行为。

这是在C#中的例子:

public class MimeType 
{ 
    private static readonly byte[] BMP = { 66, 77 }; 
    private static readonly byte[] DOC = { 208, 207, 17, 224, 161, 177, 26, 225 }; 
    private static readonly byte[] EXE_DLL = { 77, 90 }; 
    private static readonly byte[] GIF = { 71, 73, 70, 56 }; 
    private static readonly byte[] ICO = { 0, 0, 1, 0 }; 
    private static readonly byte[] JPG = { 255, 216, 255 }; 
    private static readonly byte[] MP3 = { 255, 251, 48 }; 
    private static readonly byte[] OGG = { 79, 103, 103, 83, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 }; 
    private static readonly byte[] PDF = { 37, 80, 68, 70, 45, 49, 46 }; 
    private static readonly byte[] PNG = { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82 }; 
    private static readonly byte[] RAR = { 82, 97, 114, 33, 26, 7, 0 }; 
    private static readonly byte[] SWF = { 70, 87, 83 }; 
    private static readonly byte[] TIFF = { 73, 73, 42, 0 }; 
    private static readonly byte[] TORRENT = { 100, 56, 58, 97, 110, 110, 111, 117, 110, 99, 101 }; 
    private static readonly byte[] TTF = { 0, 1, 0, 0, 0 }; 
    private static readonly byte[] WAV_AVI = { 82, 73, 70, 70 }; 
    private static readonly byte[] WMV_WMA = { 48, 38, 178, 117, 142, 102, 207, 17, 166, 217, 0, 170, 0, 98, 206, 108 }; 
    private static readonly byte[] ZIP_DOCX = { 80, 75, 3, 4 }; 

    public static string GetMimeType(byte[] file, string fileName) 
    { 

     string mime = "application/octet-stream"; //DEFAULT UNKNOWN MIME TYPE 

     //Ensure that the filename isn't empty or null 
     if (string.IsNullOrWhiteSpace(fileName)) 
     { 
      return mime; 
     } 

     //Get the file extension 
     string extension = Path.GetExtension(fileName) == null 
           ? string.Empty 
           : Path.GetExtension(fileName).ToUpper(); 

     //Get the MIME Type 
     if (file.Take(2).SequenceEqual(BMP)) 
     { 
      mime = "image/bmp"; 
     } 
     else if (file.Take(8).SequenceEqual(DOC)) 
     { 
      mime = "application/msword"; 
     } 
     else if (file.Take(2).SequenceEqual(EXE_DLL)) 
     { 
      mime = "application/x-msdownload"; //both use same mime type 
     } 
     else if (file.Take(4).SequenceEqual(GIF)) 
     { 
      mime = "image/gif"; 
     } 
     else if (file.Take(4).SequenceEqual(ICO)) 
     { 
      mime = "image/x-icon"; 
     } 
     else if (file.Take(3).SequenceEqual(JPG)) 
     { 
      mime = "image/jpeg"; 
     } 
     else if (file.Take(3).SequenceEqual(MP3)) 
     { 
      mime = "audio/mpeg"; 
     } 
     else if (file.Take(14).SequenceEqual(OGG)) 
     { 
      if (extension == ".OGX") 
      { 
       mime = "application/ogg"; 
      } 
      else if (extension == ".OGA") 
      { 
       mime = "audio/ogg"; 
      } 
      else 
      { 
       mime = "video/ogg"; 
      } 
     } 
     else if (file.Take(7).SequenceEqual(PDF)) 
     { 
      mime = "application/pdf"; 
     } 
     else if (file.Take(16).SequenceEqual(PNG)) 
     { 
      mime = "image/png"; 
     } 
     else if (file.Take(7).SequenceEqual(RAR)) 
     { 
      mime = "application/x-rar-compressed"; 
     } 
     else if (file.Take(3).SequenceEqual(SWF)) 
     { 
      mime = "application/x-shockwave-flash"; 
     } 
     else if (file.Take(4).SequenceEqual(TIFF)) 
     { 
      mime = "image/tiff"; 
     } 
     else if (file.Take(11).SequenceEqual(TORRENT)) 
     { 
      mime = "application/x-bittorrent"; 
     } 
     else if (file.Take(5).SequenceEqual(TTF)) 
     { 
      mime = "application/x-font-ttf"; 
     } 
     else if (file.Take(4).SequenceEqual(WAV_AVI)) 
     { 
      mime = extension == ".AVI" ? "video/x-msvideo" : "audio/x-wav"; 
     } 
     else if (file.Take(16).SequenceEqual(WMV_WMA)) 
     { 
      mime = extension == ".WMA" ? "audio/x-ms-wma" : "video/x-ms-wmv"; 
     } 
     else if (file.Take(4).SequenceEqual(ZIP_DOCX)) 
     { 
      mime = extension == ".DOCX" ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/x-zip-compressed"; 
     } 

     return mime; 
    } 


} 

通知我处理DOCX文件类型不同,因为DOCX真的只是一个ZIP文件。在这种情况下,我只需检查文件扩展名,一旦我确认它具有该序列。这个例子对于一些人来说还远远没有完成,但是你可以很容易地添加你自己的。

如果您想添加更多的MIME类型,您可以获得许多不同文件类型的字节数组序列from here。还有,关于文件签名的here is another good resource

如果一切都失败了,我会做很多次遍历我正在寻找的特定类型的几个文件,并在文件的字节序列中查找模式。最后,这仍然是基本验证,不能用于100%确定文件类型的证明。

1

IIS 7以上

使用此代码,但是你需要管理的服务器

public bool CheckMimeMapExtension(string fileExtension) 
     { 
      try 
      { 

       using (
       ServerManager serverManager = new ServerManager()) 
       { 
        // connects to default app.config 
        var config = serverManager.GetApplicationHostConfiguration(); 
        var staticContent = config.GetSection("system.webServer/staticContent"); 
        var mimeMap = staticContent.GetCollection(); 

        foreach (var mimeType in mimeMap) 
        { 

         if (((String)mimeType["fileExtension"]).Equals(fileExtension, StringComparison.OrdinalIgnoreCase)) 
          return true; 

        } 

       } 
       return false; 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("An exception has occurred: \n{0}", ex.Message); 
       Console.Read(); 
      } 

      return false; 

     } 
3

这个类使用以前的答案在3种不同的方式尝试:harcoded基础上的扩展, FindMimeFromData API和使用注册表。

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Runtime.InteropServices; 

using Microsoft.Win32; 

namespace YourNamespace 
{ 
    public static class MimeTypeParser 
    { 
     [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)] 
     private extern static System.UInt32 FindMimeFromData(
       System.UInt32 pBC, 
       [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl, 
       [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, 
       System.UInt32 cbSize, 
       [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed, 
       System.UInt32 dwMimeFlags, 
       out System.UInt32 ppwzMimeOut, 
       System.UInt32 dwReserverd 
     ); 

     public static string GetMimeType(string sFilePath) 
     { 
      string sMimeType = GetMimeTypeFromList(sFilePath); 

      if (String.IsNullOrEmpty(sMimeType)) 
      { 
       sMimeType = GetMimeTypeFromFile(sFilePath); 

       if (String.IsNullOrEmpty(sMimeType)) 
       { 
        sMimeType = GetMimeTypeFromRegistry(sFilePath); 
       } 
      } 

      return sMimeType; 
     } 

     public static string GetMimeTypeFromList(string sFileNameOrPath) 
     { 
      string sMimeType = null; 
      string sExtensionWithoutDot = Path.GetExtension(sFileNameOrPath).Substring(1).ToLower(); 

      if (!String.IsNullOrEmpty(sExtensionWithoutDot) && spDicMIMETypes.ContainsKey(sExtensionWithoutDot)) 
      { 
       sMimeType = spDicMIMETypes[sExtensionWithoutDot]; 
      } 

      return sMimeType; 
     } 

     public static string GetMimeTypeFromRegistry(string sFileNameOrPath) 
     { 
      string sMimeType = null; 
      string sExtension = Path.GetExtension(sFileNameOrPath).ToLower(); 
      RegistryKey pKey = Registry.ClassesRoot.OpenSubKey(sExtension); 

      if (pKey != null && pKey.GetValue("Content Type") != null) 
      { 
       sMimeType = pKey.GetValue("Content Type").ToString(); 
      } 

      return sMimeType; 
     } 

     public static string GetMimeTypeFromFile(string sFilePath) 
     { 
      string sMimeType = null; 

      if (File.Exists(sFilePath)) 
      { 
       byte[] abytBuffer = new byte[256]; 

       using (FileStream pFileStream = new FileStream(sFilePath, FileMode.Open)) 
       { 
        if (pFileStream.Length >= 256) 
        { 
         pFileStream.Read(abytBuffer, 0, 256); 
        } 
        else 
        { 
         pFileStream.Read(abytBuffer, 0, (int)pFileStream.Length); 
        } 
       } 

       try 
       { 
        UInt32 unMimeType; 

        FindMimeFromData(0, null, abytBuffer, 256, null, 0, out unMimeType, 0); 

        IntPtr pMimeType = new IntPtr(unMimeType); 
        string sMimeTypeFromFile = Marshal.PtrToStringUni(pMimeType); 

        Marshal.FreeCoTaskMem(pMimeType); 

        if (!String.IsNullOrEmpty(sMimeTypeFromFile) && sMimeTypeFromFile != "text/plain" && sMimeTypeFromFile != "application/octet-stream") 
        { 
         sMimeType = sMimeTypeFromFile; 
        } 
       } 
       catch {} 
      } 

      return sMimeType; 
     } 

     private static readonly Dictionary<string, string> spDicMIMETypes = new Dictionary<string, string> 
     { 
      {"ai", "application/postscript"}, 
      {"aif", "audio/x-aiff"}, 
      {"aifc", "audio/x-aiff"}, 
      {"aiff", "audio/x-aiff"}, 
      {"asc", "text/plain"}, 
      {"atom", "application/atom+xml"}, 
      {"au", "audio/basic"}, 
      {"avi", "video/x-msvideo"}, 
      {"bcpio", "application/x-bcpio"}, 
      {"bin", "application/octet-stream"}, 
      {"bmp", "image/bmp"}, 
      {"cdf", "application/x-netcdf"}, 
      {"cgm", "image/cgm"}, 
      {"class", "application/octet-stream"}, 
      {"cpio", "application/x-cpio"}, 
      {"cpt", "application/mac-compactpro"}, 
      {"csh", "application/x-csh"}, 
      {"css", "text/css"}, 
      {"dcr", "application/x-director"}, 
      {"dif", "video/x-dv"}, 
      {"dir", "application/x-director"}, 
      {"djv", "image/vnd.djvu"}, 
      {"djvu", "image/vnd.djvu"}, 
      {"dll", "application/octet-stream"}, 
      {"dmg", "application/octet-stream"}, 
      {"dms", "application/octet-stream"}, 
      {"doc", "application/msword"}, 
      {"docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, 
      {"dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, 
      {"docm","application/vnd.ms-word.document.macroEnabled.12"}, 
      {"dotm","application/vnd.ms-word.template.macroEnabled.12"}, 
      {"dtd", "application/xml-dtd"}, 
      {"dv", "video/x-dv"}, 
      {"dvi", "application/x-dvi"}, 
      {"dxr", "application/x-director"}, 
      {"eps", "application/postscript"}, 
      {"etx", "text/x-setext"}, 
      {"exe", "application/octet-stream"}, 
      {"ez", "application/andrew-inset"}, 
      {"gif", "image/gif"}, 
      {"gram", "application/srgs"}, 
      {"grxml", "application/srgs+xml"}, 
      {"gtar", "application/x-gtar"}, 
      {"hdf", "application/x-hdf"}, 
      {"hqx", "application/mac-binhex40"}, 
      {"htc", "text/x-component"}, 
      {"htm", "text/html"}, 
      {"html", "text/html"}, 
      {"ice", "x-conference/x-cooltalk"}, 
      {"ico", "image/x-icon"}, 
      {"ics", "text/calendar"}, 
      {"ief", "image/ief"}, 
      {"ifb", "text/calendar"}, 
      {"iges", "model/iges"}, 
      {"igs", "model/iges"}, 
      {"jnlp", "application/x-java-jnlp-file"}, 
      {"jp2", "image/jp2"}, 
      {"jpe", "image/jpeg"}, 
      {"jpeg", "image/jpeg"}, 
      {"jpg", "image/jpeg"}, 
      {"js", "application/x-javascript"}, 
      {"kar", "audio/midi"}, 
      {"latex", "application/x-latex"}, 
      {"lha", "application/octet-stream"}, 
      {"lzh", "application/octet-stream"}, 
      {"m3u", "audio/x-mpegurl"}, 
      {"m4a", "audio/mp4a-latm"}, 
      {"m4b", "audio/mp4a-latm"}, 
      {"m4p", "audio/mp4a-latm"}, 
      {"m4u", "video/vnd.mpegurl"}, 
      {"m4v", "video/x-m4v"}, 
      {"mac", "image/x-macpaint"}, 
      {"man", "application/x-troff-man"}, 
      {"mathml", "application/mathml+xml"}, 
      {"me", "application/x-troff-me"}, 
      {"mesh", "model/mesh"}, 
      {"mid", "audio/midi"}, 
      {"midi", "audio/midi"}, 
      {"mif", "application/vnd.mif"}, 
      {"mov", "video/quicktime"}, 
      {"movie", "video/x-sgi-movie"}, 
      {"mp2", "audio/mpeg"}, 
      {"mp3", "audio/mpeg"}, 
      {"mp4", "video/mp4"}, 
      {"mpe", "video/mpeg"}, 
      {"mpeg", "video/mpeg"}, 
      {"mpg", "video/mpeg"}, 
      {"mpga", "audio/mpeg"}, 
      {"ms", "application/x-troff-ms"}, 
      {"msh", "model/mesh"}, 
      {"mxu", "video/vnd.mpegurl"}, 
      {"nc", "application/x-netcdf"}, 
      {"oda", "application/oda"}, 
      {"ogg", "application/ogg"}, 
      {"pbm", "image/x-portable-bitmap"}, 
      {"pct", "image/pict"}, 
      {"pdb", "chemical/x-pdb"}, 
      {"pdf", "application/pdf"}, 
      {"pgm", "image/x-portable-graymap"}, 
      {"pgn", "application/x-chess-pgn"}, 
      {"pic", "image/pict"}, 
      {"pict", "image/pict"}, 
      {"png", "image/png"}, 
      {"pnm", "image/x-portable-anymap"}, 
      {"pnt", "image/x-macpaint"}, 
      {"pntg", "image/x-macpaint"}, 
      {"ppm", "image/x-portable-pixmap"}, 
      {"ppt", "application/vnd.ms-powerpoint"}, 
      {"pptx","application/vnd.openxmlformats-officedocument.presentationml.presentation"}, 
      {"potx","application/vnd.openxmlformats-officedocument.presentationml.template"}, 
      {"ppsx","application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, 
      {"ppam","application/vnd.ms-powerpoint.addin.macroEnabled.12"}, 
      {"pptm","application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, 
      {"potm","application/vnd.ms-powerpoint.template.macroEnabled.12"}, 
      {"ppsm","application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, 
      {"ps", "application/postscript"}, 
      {"qt", "video/quicktime"}, 
      {"qti", "image/x-quicktime"}, 
      {"qtif", "image/x-quicktime"}, 
      {"ra", "audio/x-pn-realaudio"}, 
      {"ram", "audio/x-pn-realaudio"}, 
      {"ras", "image/x-cmu-raster"}, 
      {"rdf", "application/rdf+xml"}, 
      {"rgb", "image/x-rgb"}, 
      {"rm", "application/vnd.rn-realmedia"}, 
      {"roff", "application/x-troff"}, 
      {"rtf", "text/rtf"}, 
      {"rtx", "text/richtext"}, 
      {"sgm", "text/sgml"}, 
      {"sgml", "text/sgml"}, 
      {"sh", "application/x-sh"}, 
      {"shar", "application/x-shar"}, 
      {"silo", "model/mesh"}, 
      {"sit", "application/x-stuffit"}, 
      {"skd", "application/x-koan"}, 
      {"skm", "application/x-koan"}, 
      {"skp", "application/x-koan"}, 
      {"skt", "application/x-koan"}, 
      {"smi", "application/smil"}, 
      {"smil", "application/smil"}, 
      {"snd", "audio/basic"}, 
      {"so", "application/octet-stream"}, 
      {"spl", "application/x-futuresplash"}, 
      {"src", "application/x-wais-source"}, 
      {"sv4cpio", "application/x-sv4cpio"}, 
      {"sv4crc", "application/x-sv4crc"}, 
      {"svg", "image/svg+xml"}, 
      {"swf", "application/x-shockwave-flash"}, 
      {"t", "application/x-troff"}, 
      {"tar", "application/x-tar"}, 
      {"tcl", "application/x-tcl"}, 
      {"tex", "application/x-tex"}, 
      {"texi", "application/x-texinfo"}, 
      {"texinfo", "application/x-texinfo"}, 
      {"tif", "image/tiff"}, 
      {"tiff", "image/tiff"}, 
      {"tr", "application/x-troff"}, 
      {"tsv", "text/tab-separated-values"}, 
      {"txt", "text/plain"}, 
      {"ustar", "application/x-ustar"}, 
      {"vcd", "application/x-cdlink"}, 
      {"vrml", "model/vrml"}, 
      {"vxml", "application/voicexml+xml"}, 
      {"wav", "audio/x-wav"}, 
      {"wbmp", "image/vnd.wap.wbmp"}, 
      {"wbmxl", "application/vnd.wap.wbxml"}, 
      {"wml", "text/vnd.wap.wml"}, 
      {"wmlc", "application/vnd.wap.wmlc"}, 
      {"wmls", "text/vnd.wap.wmlscript"}, 
      {"wmlsc", "application/vnd.wap.wmlscriptc"}, 
      {"wrl", "model/vrml"}, 
      {"xbm", "image/x-xbitmap"}, 
      {"xht", "application/xhtml+xml"}, 
      {"xhtml", "application/xhtml+xml"}, 
      {"xls", "application/vnd.ms-excel"},             
      {"xml", "application/xml"}, 
      {"xpm", "image/x-xpixmap"}, 
      {"xsl", "application/xml"}, 
      {"xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, 
      {"xltx","application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, 
      {"xlsm","application/vnd.ms-excel.sheet.macroEnabled.12"}, 
      {"xltm","application/vnd.ms-excel.template.macroEnabled.12"}, 
      {"xlam","application/vnd.ms-excel.addin.macroEnabled.12"}, 
      {"xlsb","application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, 
      {"xslt", "application/xslt+xml"}, 
      {"xul", "application/vnd.mozilla.xul+xml"}, 
      {"xwd", "image/x-xwindowdump"}, 
      {"xyz", "chemical/x-xyz"}, 
      {"zip", "application/zip"} 
     }; 
    } 
} 
-1

当使用Windows Azure Web角色或运行在有限信任你的应用程序不要忘记,你将不会被允许访问注册表或者非托管代码的任何其他主机的工作。混合方法 - 将try-catch-for-registry和in-memory字典组合起来看起来像是一个很好的解决方案,它具有一切。

我用这个代码来做到这一点:

public class DefaultMimeResolver : IMimeResolver 
{ 
    private readonly IFileRepository _fileRepository; 

    public DefaultMimeResolver(IFileRepository fileRepository) 
    { 
     _fileRepository = fileRepository; 
    } 

    [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)] 
    private static extern System.UInt32 FindMimeFromData(
     System.UInt32 pBC, [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, 
     System.UInt32 cbSize, 
     [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed, 
     System.UInt32 dwMimeFlags, 
     out System.UInt32 ppwzMimeOut, 
     System.UInt32 dwReserverd); 


    public string GetMimeTypeFromFileExtension(string fileExtension) 
    { 
     if (string.IsNullOrEmpty(fileExtension)) 
     { 
      throw new ArgumentNullException("fileExtension"); 
     } 

     string mimeType = GetMimeTypeFromList(fileExtension); 

     if (String.IsNullOrEmpty(mimeType)) 
     { 
      mimeType = GetMimeTypeFromRegistry(fileExtension); 
     } 

     return mimeType; 
    } 

    public string GetMimeTypeFromFile(string filePath) 
    { 
     if (string.IsNullOrEmpty(filePath)) 
     { 
      throw new ArgumentNullException("filePath"); 
     } 

     if (!File.Exists(filePath)) 
     { 
      throw new FileNotFoundException("File not found : ", filePath); 
     } 

     string mimeType = GetMimeTypeFromList(Path.GetExtension(filePath).ToLower()); 

     if (String.IsNullOrEmpty(mimeType)) 
     { 
      mimeType = GetMimeTypeFromRegistry(Path.GetExtension(filePath).ToLower()); 

      if (String.IsNullOrEmpty(mimeType)) 
      { 
       mimeType = GetMimeTypeFromFileInternal(filePath); 
      } 
     } 

     return mimeType; 
    } 

    private string GetMimeTypeFromList(string fileExtension) 
    { 
     string mimeType = null; 

     if (fileExtension.StartsWith(".")) 
     { 
      fileExtension = fileExtension.TrimStart('.'); 
     } 

     if (!String.IsNullOrEmpty(fileExtension) && _mimeTypes.ContainsKey(fileExtension)) 
     { 
      mimeType = _mimeTypes[fileExtension]; 
     } 

     return mimeType; 
    } 

    private string GetMimeTypeFromRegistry(string fileExtension) 
    { 
     string mimeType = null; 
     try 
     { 
      RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileExtension); 

      if (key != null && key.GetValue("Content Type") != null) 
      { 
       mimeType = key.GetValue("Content Type").ToString(); 
      } 
     } 
     catch (Exception) 
     { 
      // Empty. When this code is running in limited mode accessing registry is not allowed. 
     } 

     return mimeType; 
    } 

    private string GetMimeTypeFromFileInternal(string filePath) 
    { 
     string mimeType = null; 

     if (!File.Exists(filePath)) 
     { 
      return null; 
     } 

     byte[] byteBuffer = new byte[256]; 

     using (FileStream fileStream = _fileRepository.Get(filePath)) 
     { 
      if (fileStream.Length >= 256) 
      { 
       fileStream.Read(byteBuffer, 0, 256); 
      } 
      else 
      { 
       fileStream.Read(byteBuffer, 0, (int)fileStream.Length); 
      } 
     } 

     try 
     { 
      UInt32 MimeTypeNum; 

      FindMimeFromData(0, null, byteBuffer, 256, null, 0, out MimeTypeNum, 0); 

      IntPtr mimeTypePtr = new IntPtr(MimeTypeNum); 
      string mimeTypeFromFile = Marshal.PtrToStringUni(mimeTypePtr); 

      Marshal.FreeCoTaskMem(mimeTypePtr); 

      if (!String.IsNullOrEmpty(mimeTypeFromFile) && mimeTypeFromFile != "text/plain" && mimeTypeFromFile != "application/octet-stream") 
      { 
       mimeType = mimeTypeFromFile; 
      } 
     } 
     catch 
     { 
      // Empty. 
     } 

     return mimeType; 
    } 

    private readonly Dictionary<string, string> _mimeTypes = new Dictionary<string, string> 
     { 
      {"ai", "application/postscript"}, 
      {"aif", "audio/x-aiff"}, 
      {"aifc", "audio/x-aiff"}, 
      {"aiff", "audio/x-aiff"}, 
      {"asc", "text/plain"}, 
      {"atom", "application/atom+xml"}, 
      {"au", "audio/basic"}, 
      {"avi", "video/x-msvideo"}, 
      {"bcpio", "application/x-bcpio"}, 
      {"bin", "application/octet-stream"}, 
      {"bmp", "image/bmp"}, 
      {"cdf", "application/x-netcdf"}, 
      {"cgm", "image/cgm"}, 
      {"class", "application/octet-stream"}, 
      {"cpio", "application/x-cpio"}, 
      {"cpt", "application/mac-compactpro"}, 
      {"csh", "application/x-csh"}, 
      {"css", "text/css"}, 
      {"dcr", "application/x-director"}, 
      {"dif", "video/x-dv"}, 
      {"dir", "application/x-director"}, 
      {"djv", "image/vnd.djvu"}, 
      {"djvu", "image/vnd.djvu"}, 
      {"dll", "application/octet-stream"}, 
      {"dmg", "application/octet-stream"}, 
      {"dms", "application/octet-stream"}, 
      {"doc", "application/msword"}, 
      {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, 
      {"dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, 
      {"docm", "application/vnd.ms-word.document.macroEnabled.12"}, 
      {"dotm", "application/vnd.ms-word.template.macroEnabled.12"}, 
      {"dtd", "application/xml-dtd"}, 
      {"dv", "video/x-dv"}, 
      {"dvi", "application/x-dvi"}, 
      {"dxr", "application/x-director"}, 
      {"eps", "application/postscript"}, 
      {"etx", "text/x-setext"}, 
      {"exe", "application/octet-stream"}, 
      {"ez", "application/andrew-inset"}, 
      {"gif", "image/gif"}, 
      {"gram", "application/srgs"}, 
      {"grxml", "application/srgs+xml"}, 
      {"gtar", "application/x-gtar"}, 
      {"hdf", "application/x-hdf"}, 
      {"hqx", "application/mac-binhex40"}, 
      {"htc", "text/x-component"}, 
      {"htm", "text/html"}, 
      {"html", "text/html"}, 
      {"ice", "x-conference/x-cooltalk"}, 
      {"ico", "image/x-icon"}, 
      {"ics", "text/calendar"}, 
      {"ief", "image/ief"}, 
      {"ifb", "text/calendar"}, 
      {"iges", "model/iges"}, 
      {"igs", "model/iges"}, 
      {"jnlp", "application/x-java-jnlp-file"}, 
      {"jp2", "image/jp2"}, 
      {"jpe", "image/jpeg"}, 
      {"jpeg", "image/jpeg"}, 
      {"jpg", "image/jpeg"}, 
      {"js", "application/x-javascript"}, 
      {"kar", "audio/midi"}, 
      {"latex", "application/x-latex"}, 
      {"lha", "application/octet-stream"}, 
      {"lzh", "application/octet-stream"}, 
      {"m3u", "audio/x-mpegurl"}, 
      {"m4a", "audio/mp4a-latm"}, 
      {"m4b", "audio/mp4a-latm"}, 
      {"m4p", "audio/mp4a-latm"}, 
      {"m4u", "video/vnd.mpegurl"}, 
      {"m4v", "video/x-m4v"}, 
      {"mac", "image/x-macpaint"}, 
      {"man", "application/x-troff-man"}, 
      {"mathml", "application/mathml+xml"}, 
      {"me", "application/x-troff-me"}, 
      {"mesh", "model/mesh"}, 
      {"mid", "audio/midi"}, 
      {"midi", "audio/midi"}, 
      {"mif", "application/vnd.mif"}, 
      {"mov", "video/quicktime"}, 
      {"movie", "video/x-sgi-movie"}, 
      {"mp2", "audio/mpeg"}, 
      {"mp3", "audio/mpeg"}, 
      {"mp4", "video/mp4"}, 
      {"mpe", "video/mpeg"}, 
      {"mpeg", "video/mpeg"}, 
      {"mpg", "video/mpeg"}, 
      {"mpga", "audio/mpeg"}, 
      {"ms", "application/x-troff-ms"}, 
      {"msh", "model/mesh"}, 
      {"mxu", "video/vnd.mpegurl"}, 
      {"nc", "application/x-netcdf"}, 
      {"oda", "application/oda"}, 
      {"ogg", "application/ogg"}, 
      {"pbm", "image/x-portable-bitmap"}, 
      {"pct", "image/pict"}, 
      {"pdb", "chemical/x-pdb"}, 
      {"pdf", "application/pdf"}, 
      {"pgm", "image/x-portable-graymap"}, 
      {"pgn", "application/x-chess-pgn"}, 
      {"pic", "image/pict"}, 
      {"pict", "image/pict"}, 
      {"png", "image/png"}, 
      {"pnm", "image/x-portable-anymap"}, 
      {"pnt", "image/x-macpaint"}, 
      {"pntg", "image/x-macpaint"}, 
      {"ppm", "image/x-portable-pixmap"}, 
      {"ppt", "application/vnd.ms-powerpoint"}, 
      {"pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, 
      {"potx", "application/vnd.openxmlformats-officedocument.presentationml.template"}, 
      {"ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, 
      {"ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"}, 
      {"pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, 
      {"potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"}, 
      {"ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, 
      {"ps", "application/postscript"}, 
      {"qt", "video/quicktime"}, 
      {"qti", "image/x-quicktime"}, 
      {"qtif", "image/x-quicktime"}, 
      {"ra", "audio/x-pn-realaudio"}, 
      {"ram", "audio/x-pn-realaudio"}, 
      {"ras", "image/x-cmu-raster"}, 
      {"rdf", "application/rdf+xml"}, 
      {"rgb", "image/x-rgb"}, 
      {"rm", "application/vnd.rn-realmedia"}, 
      {"roff", "application/x-troff"}, 
      {"rtf", "text/rtf"}, 
      {"rtx", "text/richtext"}, 
      {"sgm", "text/sgml"}, 
      {"sgml", "text/sgml"}, 
      {"sh", "application/x-sh"}, 
      {"shar", "application/x-shar"}, 
      {"silo", "model/mesh"}, 
      {"sit", "application/x-stuffit"}, 
      {"skd", "application/x-koan"}, 
      {"skm", "application/x-koan"}, 
      {"skp", "application/x-koan"}, 
      {"skt", "application/x-koan"}, 
      {"smi", "application/smil"}, 
      {"smil", "application/smil"}, 
      {"snd", "audio/basic"}, 
      {"so", "application/octet-stream"}, 
      {"spl", "application/x-futuresplash"}, 
      {"src", "application/x-wais-source"}, 
      {"sv4cpio", "application/x-sv4cpio"}, 
      {"sv4crc", "application/x-sv4crc"}, 
      {"svg", "image/svg+xml"}, 
      {"swf", "application/x-shockwave-flash"}, 
      {"t", "application/x-troff"}, 
      {"tar", "application/x-tar"}, 
      {"tcl", "application/x-tcl"}, 
      {"tex", "application/x-tex"}, 
      {"texi", "application/x-texinfo"}, 
      {"texinfo", "application/x-texinfo"}, 
      {"tif", "image/tiff"}, 
      {"tiff", "image/tiff"}, 
      {"tr", "application/x-troff"}, 
      {"tsv", "text/tab-separated-values"}, 
      {"txt", "text/plain"}, 
      {"ustar", "application/x-ustar"}, 
      {"vcd", "application/x-cdlink"}, 
      {"vrml", "model/vrml"}, 
      {"vxml", "application/voicexml+xml"}, 
      {"wav", "audio/x-wav"}, 
      {"wbmp", "image/vnd.wap.wbmp"}, 
      {"wbmxl", "application/vnd.wap.wbxml"}, 
      {"wml", "text/vnd.wap.wml"}, 
      {"wmlc", "application/vnd.wap.wmlc"}, 
      {"wmls", "text/vnd.wap.wmlscript"}, 
      {"wmlsc", "application/vnd.wap.wmlscriptc"}, 
      {"wrl", "model/vrml"}, 
      {"xbm", "image/x-xbitmap"}, 
      {"xht", "application/xhtml+xml"}, 
      {"xhtml", "application/xhtml+xml"}, 
      {"xls", "application/vnd.ms-excel"}, 
      {"xml", "application/xml"}, 
      {"xpm", "image/x-xpixmap"}, 
      {"xsl", "application/xml"}, 
      {"xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, 
      {"xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, 
      {"xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"}, 
      {"xltm", "application/vnd.ms-excel.template.macroEnabled.12"}, 
      {"xlam", "application/vnd.ms-excel.addin.macroEnabled.12"}, 
      {"xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, 
      {"xslt", "application/xslt+xml"}, 
      {"xul", "application/vnd.mozilla.xul+xml"}, 
      {"xwd", "image/x-xwindowdump"}, 
      {"xyz", "chemical/x-xyz"}, 
      {"zip", "application/zip"} 
     }; 
} 
2

这个答案是笔者的回答(理查德·古尔利)的副本,但改进来解决IIS问题8/win2012(其中功能会导致应用程序池崩溃)的基础上罗兰的评论指向http://www.pinvoke.net/default.aspx/urlmon.findmimefromdata

using System.Runtime.InteropServices; 

...

public static string GetMimeFromFile(string filename) 
{ 

    if (!File.Exists(filename)) 
     throw new FileNotFoundException(filename + " not found"); 

    const int maxContent = 256; 

    var buffer = new byte[maxContent]; 
    using (var fs = new FileStream(filename, FileMode.Open)) 
    { 
     if (fs.Length >= maxContent) 
      fs.Read(buffer, 0, maxContent); 
     else 
      fs.Read(buffer, 0, (int) fs.Length); 
    } 

    var mimeTypePtr = IntPtr.Zero; 
    try 
    { 
     var result = FindMimeFromData(IntPtr.Zero, null, buffer, maxContent, null, 0, out mimeTypePtr, 0); 
     if (result != 0) 
     { 
      Marshal.FreeCoTaskMem(mimeTypePtr); 
      throw Marshal.GetExceptionForHR(result); 
     } 

     var mime = Marshal.PtrToStringUni(mimeTypePtr); 
     Marshal.FreeCoTaskMem(mimeTypePtr); 
     return mime; 
    } 
    catch (Exception e) 
    { 
     if (mimeTypePtr != IntPtr.Zero) 
     { 
      Marshal.FreeCoTaskMem(mimeTypePtr); 
     } 
     return "unknown/unknown"; 
    } 
} 

[DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)] 
private static extern int FindMimeFromData(IntPtr pBC, 
    [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl, 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 3)] byte[] pBuffer, 
    int cbSize, 
    [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed, 
    int dwMimeFlags, 
    out IntPtr ppwzMimeOut, 
    int dwReserved); 
2

@Steve Morgan和@Richard Gourlay这是一个很好的解决方案,非常感谢。一个小缺点是,当一个文件中的字节数是255或更低时,MIME类型有时会产生“application/octet-stream”,这对于预计会产生“text/plain”的文件稍微不准确。我已更新您的原始方法以解决此情况,如下所示:

如果文件中的字节数小于或等于255并且推导的MIME类型为“application/octet-stream”,则创建一个新的字节数组由重复n次的原始文件字节组成,直到字节的总数大于等于256.然后重新检查该新字节数组上的mime类型。

修饰方法:

Imports System.Runtime.InteropServices 

<DllImport("urlmon.dll", CharSet:=CharSet.Auto)> _ 
Private Shared Function FindMimeFromData(pBC As System.UInt32, <MarshalAs(UnmanagedType.LPStr)> pwzUrl As System.String, <MarshalAs(UnmanagedType.LPArray)> pBuffer As Byte(), cbSize As System.UInt32, <MarshalAs(UnmanagedType.LPStr)> pwzMimeProposed As System.String, dwMimeFlags As System.UInt32, _ 
ByRef ppwzMimeOut As System.UInt32, dwReserverd As System.UInt32) As System.UInt32 
End Function 
Private Function GetMimeType(ByVal f As FileInfo) As String 
    'See http://stackoverflow.com/questions/58510/using-net-how-can-you-find-the-mime-type-of-a-file-based-on-the-file-signature 
    Dim returnValue As String = "" 
    Dim fileStream As FileStream = Nothing 
    Dim fileStreamLength As Long = 0 
    Dim fileStreamIsLessThanBByteSize As Boolean = False 

    Const byteSize As Integer = 255 
    Const bbyteSize As Integer = byteSize + 1 

    Const ambiguousMimeType As String = "application/octet-stream" 
    Const unknownMimeType As String = "unknown/unknown" 

    Dim buffer As Byte() = New Byte(byteSize) {} 
    Dim fnGetMimeTypeValue As New Func(Of Byte(), Integer, String)(
     Function(_buffer As Byte(), _bbyteSize As Integer) As String 
      Dim _returnValue As String = "" 
      Dim mimeType As UInt32 = 0 
      FindMimeFromData(0, Nothing, _buffer, _bbyteSize, Nothing, 0, mimeType, 0) 
      Dim mimeTypePtr As IntPtr = New IntPtr(mimeType) 
      _returnValue = Marshal.PtrToStringUni(mimeTypePtr) 
      Marshal.FreeCoTaskMem(mimeTypePtr) 
      Return _returnValue 
     End Function) 

    If (f.Exists()) Then 
     Try 
      fileStream = New FileStream(f.FullName(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite) 
      fileStreamLength = fileStream.Length() 

      If (fileStreamLength >= bbyteSize) Then 
       fileStream.Read(buffer, 0, bbyteSize) 
      Else 
       fileStreamIsLessThanBByteSize = True 
       fileStream.Read(buffer, 0, CInt(fileStreamLength)) 
      End If 

      returnValue = fnGetMimeTypeValue(buffer, bbyteSize) 

      If (returnValue.Equals(ambiguousMimeType, StringComparison.OrdinalIgnoreCase) AndAlso fileStreamIsLessThanBByteSize AndAlso fileStreamLength > 0) Then 
       'Duplicate the stream content until the stream length is >= bbyteSize to get a more deterministic mime type analysis. 
       Dim currentBuffer As Byte() = buffer.Take(fileStreamLength).ToArray() 
       Dim repeatCount As Integer = Math.Floor((bbyteSize/fileStreamLength) + 1) 
       Dim bBufferList As List(Of Byte) = New List(Of Byte) 
       While (repeatCount > 0) 
        bBufferList.AddRange(currentBuffer) 
        repeatCount -= 1 
       End While 
       Dim bbuffer As Byte() = bBufferList.Take(bbyteSize).ToArray() 
       returnValue = fnGetMimeTypeValue(bbuffer, bbyteSize) 
      End If 
     Catch ex As Exception 
      returnValue = unknownMimeType 
     Finally 
      If (fileStream IsNot Nothing) Then fileStream.Close() 
     End Try 
    End If 
    Return returnValue 
End Function 
0

我最终使用Winista MimeDetector从Netomatix。来源可以免费下载您创建一个帐户后:http://www.netomatix.com/Products/DocumentManagement/MimeDetector.aspx

MimeTypes g_MimeTypes = new MimeTypes("mime-types.xml"); 
sbyte [] fileData = null; 

using (System.IO.FileStream srcFile = new System.IO.FileStream(strFile, System.IO.FileMode.Open)) 
{ 
    byte [] data = new byte[srcFile.Length]; 
    srcFile.Read(data, 0, (Int32)srcFile.Length); 
    fileData = Winista.Mime.SupportUtil.ToSByteArray(data); 
} 

MimeType oMimeType = g_MimeTypes.GetMimeType(fileData); 

这是这里回答另一个问题的一部分:Alternative to FindMimeFromData method in Urlmon.dll one which has more MIME types 解决这一问题的最佳解决方案在我看来。

0

Winista MIME检测用的URLmon在这里下载项目: https://github.com/MeaningOfLights/MimeDetect

说有人重命名一个exe有一个jpg扩展,你仍然可以用确定的二进制分析“真实”的文件格式。它不会检测到swf或flv,但几乎可以完成其他众所周知的格式+您可以使用十六进制编辑器并添加更多可检测的文件。

文件魔术

Winista检测使用包含有关文件类型的信息和用于标识内容type.eg签名的XML文件“的mime-type.xml”真正的MIME类型:

<!-- 
! Audio primary type 
! --> 

<mime-type name="audio/basic" 
      description="uLaw/AU Audio File"> 
    <ext>au</ext><ext>snd</ext> 
    <magic offset="0" type="byte" value="2e736e64000000"/> 
</mime-type> 

<mime-type name="audio/midi" 
      description="Musical Instrument Digital Interface MIDI-sequention Sound"> 
    <ext>mid</ext><ext>midi</ext><ext>kar</ext> 
    <magic offset="0" value="MThd"/> 
</mime-type> 

<mime-type name="audio/mpeg" 
      description="MPEG Audio Stream, Layer III"> 
    <ext>mp3</ext><ext>mp2</ext><ext>mpga</ext> 
    <magic offset="0" value="ID3"/> 
</mime-type> 

当Winista失败的检测到真正的文件格式,我已经使出回URLMON方法:

public class urlmonMimeDetect 
{ 
    [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)] 
    private extern static System.UInt32 FindMimeFromData(
     System.UInt32 pBC, 
     [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, 
     System.UInt32 cbSize, 
     [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed, 
     System.UInt32 dwMimeFlags, 
     out System.UInt32 ppwzMimeOut, 
     System.UInt32 dwReserverd 
    ); 

public string GetMimeFromFile(string filename) 
{ 
    if (!File.Exists(filename)) 
     throw new FileNotFoundException(filename + " not found"); 

    byte[] buffer = new byte[256]; 
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) 
    { 
     if (fs.Length >= 256) 
      fs.Read(buffer, 0, 256); 
     else 
      fs.Read(buffer, 0, (int)fs.Length); 
    } 
    try 
    { 
     System.UInt32 mimetype; 
     FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0); 
     System.IntPtr mimeTypePtr = new IntPtr(mimetype); 
     string mime = Marshal.PtrToStringUni(mimeTypePtr); 
     Marshal.FreeCoTaskMem(mimeTypePtr); 
     return mime; 
    } 
    catch (Exception e) 
    { 
     return "unknown/unknown"; 
    } 
} 
} 

从Winista方法中,我回到URLMon这里:

public MimeType GetMimeTypeFromFile(string filePath) 
    { 
     sbyte[] fileData = null; 
     using (FileStream srcFile = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
     { 
      byte[] data = new byte[srcFile.Length]; 
      srcFile.Read(data, 0, (Int32)srcFile.Length); 
      fileData = Winista.Mime.SupportUtil.ToSByteArray(data); 
     } 

     MimeType oMimeType = GetMimeType(fileData); 
     if (oMimeType != null) return oMimeType; 

     //We haven't found the file using Magic (eg a text/plain file) 
     //so instead use URLMon to try and get the files format 
     Winista.MimeDetect.URLMONMimeDetect.urlmonMimeDetect urlmonMimeDetect = new Winista.MimeDetect.URLMONMimeDetect.urlmonMimeDetect(); 
     string urlmonMimeType = urlmonMimeDetect.GetMimeFromFile(filePath); 
     if (!string.IsNullOrEmpty(urlmonMimeType)) 
     { 
      foreach (MimeType mimeType in types) 
      { 
       if (mimeType.Name == urlmonMimeType) 
       { 
        return mimeType; 
       } 
      } 
     } 

     return oMimeType; 
    } 
相关问题