如何通过浏览器确定上传文件的MIMEtypes?

我有一个Web应用程序,用户需要上传.zip文件。 在服务器端,我正在检查上传文件的MIMEtypes,以确保它是application/x-zip-compressedapplication/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 = kPrimaryMappingskPrimaryMappingskSecondaryMappings )。

例如:从安装了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行附近。您正在寻找defaultMimeEntriesextraMimeEntries

使用我当前的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不能被推断