如何使用C#识别文件的扩展名/类型?

我有一个工作流程,允许用户上传任何文件,然后将读取该文件。

现在我的问题是,如果用户有图像文件xyz.jpg并且他只将其重命名为xyz(扩展已删除),我们仍然可以使用/读取文件数据/元数据获取文件的类型/扩展名。

谢谢大家

有关更多详细信息,请参见PInvoke.net

[DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)] 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); 

样品用法:

  public string MimeTypeFrom(byte[] dataBytes, string mimeProposed) { if (dataBytes == null) throw new ArgumentNullException("dataBytes"); string mimeRet = String.Empty; IntPtr suggestPtr = IntPtr.Zero, filePtr = IntPtr.Zero, outPtr = IntPtr.Zero; if (mimeProposed != null && mimeProposed.Length > 0) { //suggestPtr = Marshal.StringToCoTaskMemUni(mimeProposed); // for your experiments ;-) mimeRet = mimeProposed; } int ret = FindMimeFromData(IntPtr.Zero, null, dataBytes, dataBytes.Length, mimeProposed, 0, out outPtr, 0); if (ret == 0 && outPtr != IntPtr.Zero) { //todo: this leaks memory outPtr must be freed return Marshal.PtrToStringUni(outPtr); } return mimeRet; } // call it this way: Trace.Write("MimeType is " + MimeTypeFrom(Encoding.ASCII.GetBytes("%PDF-"), "text/plain")); 

另一个例子:

 ///  /// Ensures that file exists and retrieves the content type ///  ///  /// Returns for instance "images/jpeg"  public static string getMimeFromFile(string file) { IntPtr mimeout; if (!System.IO.File.Exists(file)) throw new FileNotFoundException(file + " not found"); int MaxContent = (int)new FileInfo(file).Length; if (MaxContent > 4096) MaxContent = 4096; FileStream fs = File.OpenRead(file); byte[] buf = new byte[MaxContent]; fs.Read(buf, 0, MaxContent); fs.Close(); int result = FindMimeFromData(IntPtr.Zero, file, buf, MaxContent, null, 0, out mimeout, 0); if (result != 0) throw Marshal.GetExceptionForHR(result); string mime = Marshal.PtrToStringUni(mimeout); Marshal.FreeCoTaskMem(mimeout); return mime; } 

您可以在urlmon.dll中使用非托管函数FindMimeFromData 。

 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 ); 

请参阅此处以获取示例用法。

是的,可能对于许多文件类型这是可能的,但它需要根据具体情况解析文件的二进制内容。

是否需要检测特定的文件格式? 如果您可以将其缩小到可以由文件内容识别的几种格式,则可以使任务变得更加容易。

如果您需要检测各种文件类型,可以使用第三方工具包,但我会警告您,它们往往非常昂贵。 我熟悉的两个是Stellent(现在的Oracle)的Outside In和Autonomy Keyview 。 两者都提供程序员工具包。

如果您只需要查看上传的文件是否为图像,只需相应地解析即可

 try { Image image = Bitmap.FromStream(fileData); } catch(Exception e) { // this isn't an image. }