
在web应用中,文件上传功能通常需要对上传文件的类型进行限制,以防止恶意文件或不符合规范的文件进入系统。常见的客户端验证方法包括检查文件扩展名(如.jpg, .png)或利用浏览器提供的file.type属性。然而,这些方法都存在局限性:
为了实现更可靠的客户端文件类型验证,我们需要深入文件内容,识别其真实的MIME类型。一种有效的方法是检查文件的“魔术数字”(Magic Number),即文件开头的特定字节序列。
魔术数字是文件类型标识符,它们是文件内容最开头的几个字节。不同的文件类型有其独特的魔术数字,例如:
通过读取文件的这些起始字节并将其转换为十六进制字符串,我们可以与已知的文件魔术数字进行比对,从而准确判断文件的真实类型,即便其扩展名已被修改。
在尝试实现基于魔术数字的验证时,开发者可能会首先想到在文件输入框的change事件中进行处理。例如:
$('#myfiles').on('change', function() {
var files = $(this).get(0).files;
if (files.length > 0) {
var file = files[0];
var fileReader = new FileReader();
fileReader.onloadend = function(e) {
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
var header = '';
for (var i = 0; i < arr.length; i++) {
header += arr[i].toString(16);
}
// 进行魔术数字检查
if (header !== '89504e47' /* ... */) {
alert("文件类型不被允许!");
// 如何阻止 jQuery-File-Upload 上传?
} else {
// 在这里初始化或触发 jQuery-File-Upload
// 这种方式可能导致 jQuery-File-Upload 无法正确捕获文件或状态不一致
$('#myfile_mydrive').fileupload({ /* ... */ });
}
};
fileReader.readAsArrayBuffer(file);
}
});这种方法存在以下问题:
jQuery-File-Upload插件提供了一个强大的add回调函数,它在文件被添加到上传队列时触发,但在实际上传开始之前执行。这是进行文件内容验证的理想时机。通过将魔术数字检查逻辑放入add回调中,我们可以决定是否允许文件进入上传流程。
首先,确保你的HTML结构包含一个文件输入框,并被jQuery-File-Upload插件的容器包裹:
<div id="myfile_mydrive" class="fileupload">
<div class="fileinput-button btn btn-success btn-sm">
<i class="fa fa-paperclip"></i>
<span>浏览文件</span>
<input type="file" id="myfiles" name="myfiles">
</div>
<table role="presentation" class="table table-striped">
<tbody class="files"></tbody>
</table>
</div>接下来,在jQuery-File-Upload的初始化配置中,修改add回调函数:
$(function () {
'use strict';
$('#myfile_mydrive').fileupload({
// 'add' 回调在文件被添加到上传队列时触发
add: function (e, data) {
var file = data.files[0]; // 获取当前批次中的第一个文件
if (!file) {
alert("请选择一个文件进行上传。");
return;
}
var fileReader = new FileReader();
fileReader.onload = function (event) {
// 读取文件的前4个字节
var arr = (new Uint8Array(event.target.result)).subarray(0, 4);
var header = "";
for (var i = 0; i < arr.length; i++) {
header += arr[i].toString(16).padStart(2, '0'); // 确保两位十六进制表示
}
// 定义允许的文件类型魔术数字列表
var allowedHeaders = [
'89504e47', // PNG
'47494638', // GIF
'ffd8ffe0', 'ffd8ffe1', 'ffd8ffe2', 'ffd8ffe3', // JPEG (常见的JFIF/Exif变体)
'ffd8ffdb', 'ffd8ffee', // JPEG 其他变体
'25504446' // PDF
// 如需支持其他类型,请在此添加对应的魔术数字
];
// 检查文件头是否在允许的列表中
if (allowedHeaders.indexOf(header.toLowerCase()) === -1) {
alert("文件类型不匹配或不被允许。请上传PNG, GIF, JPEG或PDF文件。");
// 阻止文件上传
return;
} else {
// 如果验证通过,则提交文件进行上传
data.submit();
}
};
// 以 ArrayBuffer 格式读取文件内容
fileReader.readAsArrayBuffer(file);
},
// 其他配置项
downloadTemplateId: 'template-download-gallery', // 下载模板ID
uploadTemplateId: 'template-upload-gallery', // 上传模板ID
paramName: 'files[]', // 上传文件参数名
url: 'mydrive-upload.php', // 服务器上传处理URL
dataType: 'json', // 服务器返回数据类型
autoUpload: false, // **重要:设置为false,以便在验证后手动调用data.submit()**
maxNumberOfFiles: 10, // 最大上传文件数
// 这里的acceptFileTypes是基于扩展名的初步过滤,不作为最终验证手段
acceptFileTypes: /(\.|\/)(pdf|gif|jpe?g|png)$/i,
});
});通过将基于文件魔术数字的MIME类型验证逻辑集成到jQuery-File-Upload插件的add回调函数中,并配合autoUpload: false配置,我们能够实现一个强大且可靠的客户端文件类型检查机制。这不仅提升了用户体验,减少了无效上传,更重要的是,它为文件上传增加了一层重要的安全防护,有效抵御了通过修改文件扩展名来绕过验证的攻击尝试。但请务必记住,客户端验证始终是辅助手段,服务器端的严格验证才是保障系统安全的关键。
以上就是jQuery File Upload中基于文件头魔术数字的MIME类型验证教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号