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

时间:2010-05-13 12:46:14

标签: c#

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

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

全部谢谢

5 个答案:

答案 0 :(得分:13)

有关详细信息,请参阅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"));

另一个例子:

/// <summary>
/// Ensures that file exists and retrieves the content type 
/// </summary>
/// <param name="file"></param>
/// <returns>Returns for instance "images/jpeg" </returns>
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;
}

答案 1 :(得分:3)

您可以在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
);

有关示例用法,请参阅here

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

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