使用.NET,如何根据文件签名而不是扩展名找到文件的mime类型
时间:2020-03-05 18:52:04 来源:igfitidea点击:
我正在寻找一种简单的方法来获取文件扩展名不正确或者未给出的mime类型,类似于仅在.Net中的此问题。
解决方案
回答
在Urlmon.dll中,有一个名为FindMimeFromData
的函数。
从文档中
MIME type detection, or "data sniffing," refers to the process of determining an appropriate MIME type from binary data. The final result depends on a combination of server-supplied MIME type headers, file extension, and/or the data itself. Usually, only the first 256 bytes of data are significant.
因此,从文件中读取第一个(最多)256个字节,并将其传递给FindMimeFromData
。
回答
最后我确实使用了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"; } }
回答
我们也可以在注册表中查找。
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,我们都必须使用一种或者多种方式进入MIME数据库,而琐碎的Windows注册表就是这样一个地方。
对于平台独立的解决方案,尽管必须将该DB附带代码(或者作为独立库)。
回答
我认为正确的答案是史蒂夫·摩根(Steve Morgan)和塞尔吉(Serguei)的答案的结合。这就是Internet Explorer的工作方式。对FindMimeFromData
的pinvoke调用仅适用于26种硬编码的mime类型。而且,即使可能存在更具体,更合适的mime类型,它也会给出模棱两可的mime类型(例如" text / plain"或者" application / octet-stream")。如果无法提供良好的mime类型,则可以转到注册表以获取更特定的mime类型。服务器注册表可能具有更多最新的mime类型。
请参阅:http://msdn.microsoft.com/en-us/library/ms775147(VS.85).aspx