代码之家  ›  专栏  ›  技术社区  ›  Anil Namde

如何使用c_标识文件的扩展名/类型?

c#
  •  6
  • Anil Namde  · 技术社区  · 14 年前

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

    现在我的问题是,如果用户有图像文件xyz.jpg,并且将其重命名为xyz only(扩展名已删除),那么我们仍然可以使用/reading files data/metadata获取文件的类型/扩展名。

    谢谢大家

    5 回复  |  直到 14 年前
        1
  •  12
  •   Sky Sanders    14 年前

    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;
    }
    
        2
  •  3
  •   Community Jaime Torres    7 年前

    可以使用非托管函数 FindMimeFromData 在URLMONDLL中。

    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 例如用法。

        3
  •  2
  •   spender    14 年前

    是的,对于许多文件类型来说,这是可能的,但是它需要逐个分析文件的二进制内容。

        4
  •  0
  •   JohnFx    14 年前

    您是否需要检测特定的文件格式?如果您可以将其缩小到几个可以由文件内容标识的格式,那么这将使任务变得容易得多。

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

        5
  •  0
  •   Kurru    14 年前

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

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