替代Urlmon.dll中具有更多MIME类型的FindMimeFromData方法

通过Windows DLL Urlmon.dll可访问的FindMimeFromData方法能够确定存储在内存中的给定数据的MIME类型,考虑到存储此类数据的字节数组的前256个字节。

然而,在阅读了它的文档后,我在Windows Internet Explorer中引导了MIME类型检测,在那里我可以找到此方法能够识别的MIME类型。 见清单 。 如您所见,此方法仅限于26种MIME类型。

所以我想知道是否有人能指出我有更多MIME类型的另一种方法,或者另外一种方法/类我可以包含我认为合适的MIME类型。

谢谢。

所以我想知道是否有人能指出我有更多MIME类型的另一种方法,或者另外一种方法/类我可以包含我认为合适的MIME类型。

我使用Winista和URLMon的混合来检测上传文件真实格式。

下载Winista: http : //www.netomatix.com/Products/DocumentManagement/MimeDetector.aspx

或者使用URLMon下载项目: https : //github.com/MeaningOfLights/MimeDetect

Winista MIME检测

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

文件魔术

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

   ausnd    midmidikar    mp3mp2mpga   

当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; } 

来自netomatix的Winista 。 AFAIK是一个基于2000年初开源Java项目的C#重写。 请享用!

您也可以使用由Paul Zahra链接的post中提到的Registry方法或.Net 4.5方法 ,但Winista是最好的恕我直言。

更新:

对于桌面应用程序,您可能会发现WindowsAPICodePack更好用:

 using Microsoft.WindowsAPICodePack.Shell; using Microsoft.WindowsAPICodePack.Shell.PropertySystem; private static string GetFilePropertyItemTypeTextValueFromShellFile(string filePathWithExtension) { var shellFile = ShellFile.FromFilePath(filePathWithExtension); var prop = shellFile.Properties.GetProperty(PItemTypeTextCanonical); return prop.FormatForDisplay(PropertyDescriptionFormatOptions.None); } 

在这个SOpost中有多种可能的解决方案,它们至少会给你一些思考的食物。

似乎唯一真正的方法是以二进制方式读取它然后进行比较,无论MIME类型是以某种方式声明为硬编码还是依赖于机器自己的MIME类型/注册表。