为啥 FindMimeFromData 可以识别一台主机上的图像/tiff,但不能识别另一台主机上的图像/tiff?
Posted
技术标签:
【中文标题】为啥 FindMimeFromData 可以识别一台主机上的图像/tiff,但不能识别另一台主机上的图像/tiff?【英文标题】:Why does FindMimeFromData recognize image/tiff on one host, but doesn't on another one?为什么 FindMimeFromData 可以识别一台主机上的图像/tiff,但不能识别另一台主机上的图像/tiff? 【发布时间】:2011-10-01 02:38:04 【问题描述】:我正在使用来自urlmon.dll
的FindMimeFromData
来嗅探上传文件的 MIME 类型。根据MIME Type Detection in Internet Explorer,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);
// ...
【问题讨论】:
放弃:IIS 正在使用什么?你有关联的 IIS MIME 类型吗?虽然 .tif 文件与一个程序相关联,但这并不意味着 MIME 类型已在 IIS 中注册 您是否将pwzUrl
或pBuffer
参数与FindMimeFromData
一起使用?
@Aoi:我使用pBuffer
。我将使用实际代码更新问题。
@Daniel:IIS6 安装在该服务器上,并且定义了 .tif 和 .tiff 的 MIME 类型(图像/tiff),尽管我怀疑这对此有任何影响。这段代码 (urlmon.dll
) 是 IE 的一部分,可以在没有 IIS 的机器上使用,所以我看不出 IIS 版本或配置如何影响结果。
这是对所有 TIFF 文件失败还是仅对一个文件失败?否则,您确定 MIME 嗅探是测试机器上启用的 IE 功能(IE 区域也可以禁用此功能...)msdn.microsoft.com/en-us/library/ms537169(v=vs.85).aspx
【参考方案1】:
我无法重现您的问题,但是我对该主题进行了一些研究。我相信正如您所怀疑的那样,问题出在 MIME 类型检测的第 2 步:urlmon.dll v9 中的硬编码测试与 urlmon.dll v8 中的不同。
TIFF 上的 Wikipedia 文章显示了格式的复杂性,而这从一开始就是一个问题:
在引入 TIFF 时,它的可扩展性引发了兼容性问题。编码的灵活性引发了一个笑话,即 TIFF 代表 数千种不兼容的文件格式。
TIFF Compression Tag 部分清楚地显示了许多罕见的压缩方案,正如我怀疑的那样,在早期版本的 IE 中创建 urlmon.dll 硬编码测试时已将其省略。
那么,有什么办法可以解决这个问题呢?我可以想到三种解决方案,但是每种解决方案都会带来不同类型的新问题:
-
将开发机器上的 IE 更新到版本 9。
在您的开发机器上应用最新的 IE 8 更新。众所周知,urlmon.dll 的修改版本经常被引入(例如KB974455)。其中之一可能包含更新的 MIME 硬编码测试。
随您的应用程序分发自己的 urlmon.dll 副本。
看来解决方案 1 和 2 是您应该选择的解决方案。但是,生产环境可能存在问题。正如我的经验所示,生产环境的管理员经常出于多种原因不同意安装某些更新。说服管理员将 IE 更新到 v9 并且更容易安装 IE8 KB 更新可能更难(正如他们应该做的那样,但我们都知道它是怎么回事)。如果您可以控制生产环境,我认为您应该使用解决方案 1。
第三种解决方案引入了两个问题:
合法:分发自己的 urlmon.dll 副本可能违反 Microsoft 的政策 编码:您必须加载the dll dynamically 才能调用FindMimeFromData
函数,或者至少自定义应用程序的清单文件,因为Dynamic-Link Library Search Order。我假设您知道,手动将较新版本的 urlmon.dll 复制到系统文件夹是一个非常糟糕的主意,因为其他应用很可能会在使用它时崩溃。
不管怎样,祝你解开你的 urlmon 之谜。
【讨论】:
感谢您的研究和建议。这解释了为什么我会看到这个问题。幸运的是,我不需要变通办法,因为这只是一台无论如何都会升级的测试机器,我们可以完全控制托管此应用程序的其他服务器。 顺便说一下,只是为了记录-该机器现在已经完全更新(IE8,所有更新都已发布)并且这个问题仍然存在,所以解决方案2已经出来了。 IE9 不适用于 Windows Server 2003 R2,因此解决方案 1 也已发布。我将等待那台机器上的操作系统升级。以上是关于为啥 FindMimeFromData 可以识别一台主机上的图像/tiff,但不能识别另一台主机上的图像/tiff?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?
为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?
为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?
为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?
替代 Urlmon.dll 中的 FindMimeFromData 方法,该方法具有更多 MIME 类型
urlmon.dll FindMimeFromData() 在 64 位桌面/控制台上完美运行,但在 ASP.NET 上生成错误