4

我使用FindMimeFromDatafromurlmon.dll来嗅探上传文件的 MIME 类型。根据Internet Explorer 中的 MIME 类型检测image/tiff是公认的 MIME 类型之一。它在我的开发机器(Windows 7 64bit,IE9)上运行良好,但在测试环境(Windows Server 2003 R2 64bit,IE8)上不起作用 - 它返回application/octet-stream而不是image/tiff.

上面的文章描述了确定 MIME 类型的确切步骤,但由于image/tiff它是 26 种可识别类型之一,它应该在第 2 步(嗅探实际数据)结束,以便文件扩展名和注册应用程序(以及其他注册表内容)应该没关系。

哦,顺便说一下,TIFF 文件实际上测试服务器上的一个程序(Windows 图片和传真查看器)相关联。并不是说 Windows 注册表中没有对 TIFF 的任何引用。

任何想法为什么它不能按预期工作?

编辑: FindMimeFromData 是这样使用的:

public class MimeUtil
{
    [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
    private 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 static string GetMimeFromData(byte[] data)
    {
        IntPtr mimetype = IntPtr.Zero;
        try
        {
            const int flags = 0x20; // FMFD_RETURNUPDATEDIMGMIMES
            int res = FindMimeFromData(IntPtr.Zero, null, data, data.Length, null, flags, out mimetype, 0);
            switch (res)
            {
                case 0:
                    string mime = Marshal.PtrToStringUni(mimetype);
                    return mime;
                // snip - error handling
                // ...
                default:
                    throw new Exception("Unexpected HRESULT " + res + " returned by FindMimeFromData (in urlmon.dll)");
            }
        }
        finally
        {
            if (mimetype != IntPtr.Zero)
                Marshal.FreeCoTaskMem(mimetype);
        }
    }
}

然后这样调用:

protected void uploader_FileUploaded(object sender, FileUploadedEventArgs e)
{
    int bsize = Math.Min(e.File.ContentLength, 256);
    byte[] buffer = new byte[bsize];
    int nbytes = e.File.InputStream.Read(buffer, 0, bsize);
    if (nbytes > 0)
        string mime = MimeUtil.GetMimeFromData(buffer);
    // ...
}
4

1 回答 1

5

我无法重现您的问题,但是我对该主题进行了一些研究。我相信正如您所怀疑的那样,问题出在 MIME 类型检测的第 2 步:urlmon.dll v9 中的硬编码测试与 urlmon.dll v8 中的硬编码测试不同。

关于TIFF的 Wikipedia 文章显示了该格式的复杂程度,而这从一开始就是一个问题:

引入 TIFF 时,它的可扩展性引发了兼容性问题。编码的灵活性引发了一个笑话,即 TIFF 代表数千种不兼容的文件格式

TIFF 压缩标签部分清楚地显示了许多罕见的压缩方案,正如我怀疑的那样,在早期版本的 IE 中创建 urlmon.dll 硬编码测试时已将其省略。

那么,有什么办法可以解决这个问题呢?我可以想到三个解决方案,但是每个解决方案都会带来不同类型的新问题:

  1. 将开发机器上的 IE 更新到版本 9。
  2. 在您的开发机器上应用最新的 IE 8 更新。众所周知,经常引入 urlmon.dll 的修改版本(例如KB974455)。其中之一可能包含更新的 MIME 硬编码测试。
  3. 与您的应用程序一起分发自己的 urlmon.dll 副本。

似乎解决方案 1 和 2 是您应该选择的解决方案。但是,生产环境可能存在问题。正如我的经验所示,生产环境的管理员经常出于多种原因不同意安装某些更新。说服管理员将 IE 更新到 v9 并且更容易安装 IE8 KB 更新可能更难(正如他们应该做的那样,但我们都知道它是怎么回事)。如果您控制生产环境,我认为您应该使用解决方案 1。

第三种解决方案引入了两个问题:

  • 合法:分发自己的 urlmon.dll 副本可能违反 Microsoft 的政策
  • 编码:由于动态链接库搜索顺序,您必须动态加载 dll以调用该FindMimeFromData函数或至少自定义应用程序的清单文件。我假设您知道,手动将更新版本的 urlmon.dll 复制到系统文件夹是一个非常糟糕的主意,因为其他应用程序很可能会在使用它时崩溃。

无论如何,祝你好运解决你的 urlmon 之谜。

于 2012-10-28T12:26:15.237 回答