如何通过浏览器确定上传文件的MIMEtypes?
我有一个Web应用程序,用户需要上传.zip文件。 在服务器端,我正在检查上传文件的MIMEtypes,以确保它是application/x-zip-compressed
或application/zip
。
这对Firefox和IE浏览器工作正常。 然而,当一个同事testing它时,他在Firefox上失败了(发送的MIMEtypes就像是“ application/octet-stream
”),但在Internet Explorer上工作。 我们的设置似乎是相同的:IE8,FF 3.5.1的所有附加组件被禁用,Win XP SP3,WinRAR作为本机.zip文件处理程序(不知道是否相关)安装。
所以我的问题是: 浏览器如何确定什么MIMEtypes发送?
请注意:我知道MIMEtypes是由浏览器发送的,因此不可靠。 我只是把它作为一个便利来检查 – 主要是为了给出比通过尝试打开非压缩文件作为zip文件而获得的错误信息更友好的错误信息,并避免加载(推测是重的)zip文件库。
铬
Chrome (写入38版本)有三种方式确定MIMEtypes,并按照一定的顺序进行。 以下片段来自文件src/net/base/mime_util.cc
,方法MimeUtil::GetMimeTypeFromExtensionHelper
。
// We implement the same algorithm as Mozilla for mapping a file extension to // a mime type. That is, we first check a hard-coded list (that cannot be // overridden), and then if not found there, we defer to the system registry. // Finally, we scan a secondary hard-coded list to catch types that we can // deduce but that we also want to allow the OS to override.
硬编码列表在文件中稍早: https : kPrimaryMappings
? kPrimaryMappings
= kPrimaryMappings
( kPrimaryMappings
和kSecondaryMappings
)。
例如:从安装了Microsoft Excel的Windows系统上传CSV文件时,Chrome会将其报告为application/vnd.ms-excel
。 这是因为.csv
没有在第一个硬编码列表中指定,所以浏览器回退到系统registry。 HKEY_CLASSES_ROOT\.csv
具有名为Content Type
的值,该值设置为application/vnd.ms-excel
。
IE浏览器
再次使用相同的例子,浏览器将报告application/vnd.ms-excel
。 我认为这是合理的假设Internet Explorer (版本11作为写作)使用registry。 它也可能使用像Chrome和Firefox这样的硬编码列表,但是它的封闭源代码很难validation。
火狐
正如Chrome代码中所指出的那样,Firefox (写作时的版本32)以类似的方式工作。 从文件uriloader\exthandler\nsExternalHelperAppService.cpp
,方法nsExternalHelperAppService::GetTypeFromExtension
// OK. We want to try the following sources of mimetype information, in this order: // 1. defaultMimeEntries array // 2. User-set preferences (managed by the handler service) // 3. OS-provided information // 4. our "extras" array // 5. Information from plugins // 6. The "ext-to-type-mapping" category
硬编码列表在文件的早些时候在441行附近。您正在寻找defaultMimeEntries
和extraMimeEntries
。
使用我当前的configuration文件,浏览器将报告text/csv
因为mimeTypes.rdf
有一个条目(上面的列表中的条目2)。 使用新的configuration文件,没有这个条目,浏览器将报告application/vnd.ms-excel
(列表中的项目3)。
概要
浏览器中的硬编码列表非常有限。 通常,浏览器发送的MIMEtypes将是操作系统报告的MIMEtypes。 这正是为什么,如问题所述,浏览器报告的MIMEtypes是不可靠的。
基普,我花了一些时间阅读RFC,MSDN和MDN。 这是我能理解的。 当浏览器遇到要上载的文件时,它会查看收到的第一个数据缓冲区,然后对其执行testing。 这些testing试图确定该文件是否是已知的MIMEtypes,如果已知的MIMEtypes,它将进一步testing已知的MIMEtypes,并据此采取行动。 我想IE试图做到这一点,而不是只从扩展确定文件types。 这个页面解释了IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx 。 对于Firefox,我可以理解的是,它试图从文件系统或目录项中读取文件信息,然后确定文件types。 这里是FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile的链接。; 我仍然希望有更多的权威信息。
这可能是操作系统和可能依赖于浏览器,但在Windows上,给定文件扩展名的MIMEtypes可以通过在HKCRregistry中find:
例如:
HKEY_CLASSES_ROOT.zip – ContentType
要从MIME到文件扩展名,您可以查看下面的键
HKEY_CLASSES_ROOT \ Mime \ Database \ Content Type
获取特定MIMEtypes的默认扩展名。
虽然这不是你的问题的答案,但它确实解决了你正在努力解决的问题。 因人而异。
正如你写的,MIMEtypes是不可靠的,因为每个浏览器都有其确定的方式。 但是,浏览器发送文件的原始名称(包括扩展名)。 所以处理这个问题的最好方法是检查文件的扩展名而不是MIMEtypes。
如果你仍然需要MIMEtypes,你可以使用你自己的apache的mime.types来确定它在服务器端。
我同意johndodo,有这么多的variables,使从浏览器发送的MIMEtypes不可靠。 我会排除收到的子types,只关注像“应用程序”这样的types。 如果您的应用程序是基于PHP的,则可以使用explode()函数轻松完成此操作。 此外,只需检查文件扩展名,以确保它是.zip或任何其他压缩你正在寻找!
根据rfc1867 – HTML格式的file upload :
如果媒体types是已知的(例如,从文件扩展名或操作系统键入信息推断出)或作为应用程序/八位字节stream,则每个部分应该标记有适当的内容types。
所以我的理解是, application/octet-stream
有点像一个全blanket catch-all
标识符,如果types不能被推断 。