我从另一个StackOverflow答案中找到了一些代码,用于根据从文件的前几个字节读取的内容来发现文件的MIME类型。该代码引用外部DLL中的非托管方法。
[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
);
我调用此方法,返回一个IntPtr,并使用Marshal.PtrToStringUni读取存储在指定内存地址的字符串。
System.UInt32 mimetype = 0;
FindMimeFromData(0, null, buffer, maxBytes, null, 0, out mimetype, 0);
System.IntPtr mimeTypePtr = new IntPtr(mimetype);
string mime = Marshal.PtrToStringUni(mimeTypePtr);
Marshal.FreeCoTaskMem(mimeTypePtr);
请注意,maxBytes硬编码为256,缓冲区最多可容纳被检查文件的前256个字节。
调用Marshal.PtrToStringUni(mimeTypePtr)会抛出一个AccessViolationException,并显示消息"尝试读取或写入受保护的内存。这通常表明其他内存已损坏。"
逻辑在Windows窗体或控制台应用程序中使用时工作正常,因此似乎只有一些安全措施才适用于ASP.Net应用程序。有谁知道从ASP.Net调用这个非托管方法需要什么?我还想找到一种更好的方法来获取不涉及使用Windows注册表的文件的MIME类型。我在使用注册表时遇到了一些问题,我试图让它在我不能依赖注册表的那些时候作为故障转移工作。
答案 0 :(得分:4)
在问题here的评论中实际解决了这个确切的情况。使用pinvoke.net上显示的FindMimeFromData方法的签名修复了我的问题。感谢@Rohland的原始评论,感谢@MikeHixson指出我正确的方向。