我已经阅读 了这个 和 这个 问题,这似乎表明可以在客户端使用 JavaScript 检查文件 MIME 类型。现在,我知道真正的验证仍然必须在服务器端完成。我想执行客户端检查以避免不必要的服务器资源浪费。
为了测试这是否可以在客户端完成,我将 JPEG
测试文件的扩展名更改为 .png
并选择要上传的文件。在发送文件之前,我使用 JavaScript 控制台查询文件对象:
document.getElementsByTagName('input')[0].files[0];
这是我在 Chrome 28.0 上得到的:
文件 {webkitRelativePath: “”, lastModifiedDate: 2012 年 10 月 16 日星期二
10:00:00 GMT+0000 (UTC),名称:“test.png”,类型:“image/png”,大小:
500055…}
它显示类型为 image/png
,这似乎表明检查是基于文件扩展名而不是 MIME 类型完成的。我尝试了 Firefox 22.0,它给了我相同的结果。但是根据 W3C 规范,应该实现 MIME 嗅探。
我是否可以说目前无法使用 JavaScript 检查 MIME 类型?还是我错过了什么?
原文由 Question Overflow 发布,翻译遵循 CC BY-SA 4.0 许可协议
在将文件上传到服务器之前,您可以使用 JavaScript 的
FileReader
轻松确定文件 MIME 类型。我同意我们应该更喜欢服务器端检查而不是客户端检查,但客户端检查仍然是可能的。我将向您展示如何操作并在底部提供一个工作演示。检查您的浏览器是否同时支持
File
和Blob
。所有主要的都应该。步骤1:
您可以像这样 ( ref ) 从
<input>
元素中检索File
信息:这是上述( ref )的拖放版本:
第2步:
我们现在可以检查文件并梳理出标题和 MIME 类型。
✘ 快速方法
您可以使用此模式天真地向 Blob 询问它所代表的任何文件的 MIME 类型:
对于图像,MIME 类型返回如下:
警告: 从文件扩展名中检测到 MIME 类型,可能会被欺骗或欺骗。可以将
.jpg
重命名为.png
并且 MIME 类型将报告为image/png
。✓ 正确的标头检查方法
要获得客户端文件的真正 MIME 类型,我们可以更进一步,检查给定文件的前几个字节,以与所谓的 幻数 进行比较。请注意,这并不完全简单,因为例如 JPEG 有一些“幻数”。这是因为格式自 1991 年以来已经发展。您可能只检查前两个字节就可以逃脱,但我更喜欢检查至少 4 个字节以减少误报。
JPEG 的示例文件签名(前 4 个字节):
这是检索文件头的基本代码:
然后,您可以像这样确定真正的 MIME 类型(更多文件签名 here 和 here ):
根据预期的 MIME 类型,根据需要接受或拒绝文件上传。
演示
这是本地文件 和 远程文件的工作演示(为了这个演示,我不得不绕过 CORS)。打开代码片段,运行它,您应该会看到显示的三个不同类型的远程图像。在顶部,您可以选择本地图像 或 数据文件,并显示文件签名和/或 MIME 类型。
请注意,即使图像被重命名,也可以确定其真正的 MIME 类型。见下文。
截屏