
在web应用中,文件上传功能常伴随着对文件类型的严格限制,以确保系统安全和数据完整性。然而,传统的客户端文件类型校验方法,如依赖 file.type 属性或检查文件扩展名,存在明显的局限性。用户可以通过简单地修改文件扩展名(例如,将一个可执行文件重命名为 .jpg),轻松绕过这些校验,从而上传恶意文件。
最初的尝试可能包括在文件输入框的 change 事件中独立执行文件头校验,并期望它能与 jQuery File Upload 插件协同工作。然而,这种分离的逻辑常常导致问题:on('change') 事件可能无法正确触发或与 fileupload 插件的内部机制冲突,导致校验结果不一致,甚至在显示“文件类型不支持”后仍允许文件上传,这表明校验逻辑与上传流程未能有效同步,且校验状态可能没有被正确清除或重置。
为了克服传统校验的不足,我们可以采用更底层的“文件头”校验方法。文件头,也称为“魔术数字”(Magic Number),是文件起始位置的一串特定字节序列,用于标识文件的真实类型。例如:
通过读取文件的前几个字节并将其与已知的文件头进行比对,我们可以准确地判断文件的真实类型,即使其扩展名已被篡改。
将文件头校验逻辑直接集成到 jQuery File Upload 插件的 add 回调函数中,是确保校验在上传前执行且与插件流程紧密结合的最佳实践。
首先,确保你的HTML结构包含一个文件输入框和用于显示上传状态的容器,这些都应被 fileupload 插件识别:
<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>这里,#myfile_mydrive 是 fileupload 插件的容器,zuojiankuohaophpcninput type="file" id="myfiles" name="myfiles"> 是实际的文件选择控件。
核心校验逻辑应放置在 fileupload 插件的 add 回调函数中。add 函数在文件被添加到上传队列时立即触发,但在实际上传请求发送之前。
$(function () {
$('#myfile_mydrive').fileupload({
// add 回调函数在文件被添加到队列时触发,是执行校验的理想位置
add: function(e, data) {
var file = data.files[0]; // 获取当前文件
var fileReader = new FileReader();
fileReader.onload = function(e_reader) {
// 读取文件的前4个字节作为文件头
var arr = (new Uint8Array(e_reader.target.result)).subarray(0, 4);
var header = "";
for (var i = 0; i < arr.length; i++) {
header += arr[i].toString(16).padStart(2, '0'); // 转换为十六进制字符串,确保两位
}
// 定义允许的文件类型及其对应的Magic Number
var allowedHeaders = [
'89504e47', // PNG
'47494638', // GIF
'ffd8ffe0', // JPEG (JFIF)
'ffd8ffe1', // JPEG (Exif)
'ffd8ffe2', // JPEG (Canon)
'25504446' // PDF
];
// 检查文件头是否在允许列表中
if (allowedHeaders.includes(header.toLowerCase())) {
// 文件类型匹配,允许上传
data.submit(); // 提交文件进行上传
} else {
// 文件类型不匹配,阻止上传并提示用户
alert("文件类型不匹配,请上传图片(PNG/GIF/JPG)或PDF文件。");
// 可以选择清除文件输入框或进行其他错误处理
// 例如:$('#myfiles').val('');
}
};
// 以 ArrayBuffer 格式读取文件内容,只读取前4个字节
fileReader.readAsArrayBuffer(file.slice(0, 4));
},
downloadTemplateId: 'template-download-gallery',
uploadTemplateId: 'template-upload-gallery',
paramName: 'files[]',
url: 'mydrive-upload.php',
dataType: 'json',
autoUpload: false, // 禁用自动上传,以便在校验后手动触发 data.submit()
maxNumberOfFiles: 10,
// acceptFileTypes 正则表达式作为初步的客户端过滤,但文件头校验更可靠
acceptFileTypes: /(\.|\/)(pdf|gif|jpe?g|png)$/i,
});
});代码详解:
通过上述方法,您可以显著增强 jQuery File Upload 功能的安全性,确保只有符合预设类型的文件才能被成功上传。
以上就是增强 jQuery 文件上传:在扩展名更改后进行可靠的 MIME 类型校验的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号