【问题标题】:How is mime type of an uploaded file determined by browser?浏览器如何确定上传文件的 mime 类型?
【发布时间】:2015-10-22 03:52:19
【问题描述】:

我有一个网络应用程序,用户需要在其中上传 .zip 文件。在服务器端,我正在检查上传文件的 MIME 类型,以确保它是 application/x-zip-compressedapplication/zip

这对我在 Firefox 和 IE 上运行良好。然而,当一位同事对其进行测试时,他在 Firefox 上失败了(发送的 mime 类型类似于“application/octet-stream”),但在 Internet Explorer 上工作。我们的设置似乎是相同的:IE8、FF 3.5.1 禁用了所有附加组件、Win XP SP3、WinRAR 安装为本机 .zip 文件处理程序(不确定是否相关)。

所以我的问题是:浏览器如何确定要发送的 MIME 类型?

请注意:我知道 mime 类型是由浏览器发送的,因此不可靠。我只是为了方便而检查它 - 主要是为了提供比通过尝试将非 zip 文件打开为 zip 文件得到的错误消息更友好的错误消息,并避免加载(可能很重的)zip 文件库。

【问题讨论】:

  • application/octet-stream 指定一个二进制文件。您应该能够获取文件的扩展名以查看它是否为 zip 文件。澄清一下,这对你在 FF 上是否有效,但对你的同事无效?
  • 是的,它在两个浏览器中都适用于我
  • 看看input/@formenctypeform/@enctype属性

标签: forms browser webforms mime-types


【解决方案1】:

Chrome (编写时为 38 版) 有 3 种方法来确定 MIME 类型,并按特定顺序进行。下面的sn-p来自文件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://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170kPrimaryMappingskSecondaryMappings)。

例如:当从安装了 Microsoft Excel 的 Windows 系统上传 CSV 文件时,Chrome 会将此报告为application/vnd.ms-excel。这是因为.csv没有在第一个硬编码列表中指定,所以浏览器回退到系统注册表。 HKEY_CLASSES_ROOT\.csv 有一个名为 Content Type 的值,该值设置为 application/vnd.ms-excel

Internet Explorer

再次使用相同的示例,浏览器将报告application/vnd.ms-excel。我认为假设 Internet Explorer (撰写时为第 11 版) 使用注册表是合理的。可能它还使用了 Chrome 和 Firefox 等硬编码列表,但它的封闭源特性使其难以验证。

火狐

如 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

使用我当前的配置文件,浏览器将报告 text/csv,因为在 mimeTypes.rdf 中有一个条目(上面列表中的第 2 项)。对于没有此条目的新配置文件,浏览器将报告 application/vnd.ms-excel(列表中的第 3 项)。

总结

浏览器中的硬编码列表非常有限。通常,浏览器发送的 MIME 类型将是操作系统报告的类型。正如问题中所述,这正是浏览器报告的 MIME 类型不可靠的原因。

【讨论】:

  • 谢谢!你有链接到 chrome 源代码中的硬编码列表吗?
  • @Kip 是的,我添加了一个链接。 Firefox 似乎没有(官方)在线源代码浏览器,我必须从他们的 FTP 服务器下载。
  • 将 MIME 作为 CSV 的 ms-excel 很烦人,想知道为什么它不在硬编码列表中。
  • 很高兴知道自 2014 年以来 mime 类型检测是否有一些更新。
  • @VitalyIsaev 粗略浏览一下 Chrome 代码表明,这自 2014 年以来没有改变。
【解决方案2】:

rfc1867 - Form-based file upload in HTML

每个部分都应标有适当的内容类型,如果 媒体类型是已知的(例如,从文件扩展名或 操作系统类型信息)或作为应用程序/八位字节流。

所以我的理解是,如果类型无法推断application/octet-stream 有点像blanket catch-all 标识符。

【讨论】:

  • 是的,我明白这一切。问题是浏览器如何推断。
  • 这值得知道,对吧?如果application/octet-stream 是包罗万象的,那么另一种方法是信任浏览器,如果它能够做出猜测,并在你得到application/octet-stream 时进行自己的服务器端测试。
【解决方案3】:

虽然这不是您问题的答案,但它确实解决了您要解决的问题。 YMMV。

正如您所写,mime 类型并不可靠,因为每个浏览器都有其确定它的方式。但是,浏览器会发送文件的原始名称(包括扩展名)。所以解决这个问题的最好方法是检查文件的扩展名而不是 MIME 类型。

如果您仍然需要 mime 类型,您可以使用自己的 apache 的 mime.types 来确定它的服务器端。

【讨论】:

  • 想详细说明一下?根据我的经验,浏览器总是发送正确的原始文件名(带扩展名),而 MIME 类型差异很大。所以是的,我会说它更可靠。
  • 正确。我的意思是说最终用户可以放置任何扩展名,而不管实际类型如何,所以它不应该被信任。
  • 确实如此,但无论您使用扩展名还是 MIME 类型都没有关系 - 您永远不应该相信用户提供的输入。但是 OP 明确表示他知道这个问题,所以这不是这个问题的一部分。顺便说一句,如果您删除了反对票,我将不胜感激(我假设它来自您)。
  • 你说得对,没注意问题中的not,我的错。我可以取消我的投票,但您必须为此编辑答案(由系统强制执行)...
  • 是的,我同意 johndodo。正如 Stijn 在上面的回答中解释的那样,Chrome 和 Firefox 首先检查扩展。他们最终都在做同样的事情。
【解决方案4】:

我同意 johndodo 的观点,有太多变量会导致从浏览器发送的 mime 类型不可靠。我会排除收到的子类型,只关注“应用程序”之类的类型。如果您的应用程序是基于 php 的,您可以使用函数 explode() 轻松完成此操作。 此外,只需检查文件扩展名以确保它是 .zip 或您正在寻找的任何其他压缩!

【讨论】:

    【解决方案5】:

    Kip,我花了一些时间阅读 RFC、MSDN 和 MDN。这是我能理解的。当浏览器遇到要上传的文件时,它会查看它接收到的第一个数据缓冲区,然后对其进行测试。这些测试试图确定文件是否是已知的 mime 类型,如果已知 mime 类型,它将简单地进一步测试它的已知 mime 类型并采取相应的措施。我认为 IE 会首先尝试执行此操作,而不仅仅是从扩展名中确定文件类型。本页为 IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx 解释了这一点。对于firefox,我能理解的是它试图从文件系统或目录条目中读取文件信息,然后确定文件类型。这是 FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile 的链接。我仍然希望有更多关于这方面的权威信息。

    【讨论】:

      【解决方案6】:

      这可能取决于操作系统,也可能取决于浏览器,但在 Windows 上,可以通过查看 HKCR 下的注册表找到给定文件扩展名的 MIME 类型:

      例如:

      HKEY_CLASSES_ROOT.zip - 内容类型

      要从 MIME 转到文件扩展名,您可以查看下面的键

      HKEY_CLASSES_ROOT\Mime\Database\内容类型

      获取特定 MIME 类型的默认扩展名。

      【讨论】:

      • 谢谢。不幸的是,对于我和我的同事来说,这在我们的注册表中似乎是正确的。我想这就是为什么它在 IE 中为他工作的原因,但 FF 以某种方式得到了不同的结果......哦,好吧:(
      猜你喜欢
      • 2012-02-02
      • 2012-03-16
      • 2012-03-09
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多