html原生实现上传需设enctype="multipart/form-data",accept仅提示类型(如accept="image/png,image/jpeg"),不可靠;必须用js校验file.type和file.name扩展名,并检查file.size,且后端须用文件头(magic bytes)二次校验真实类型与大小。

用 <input type="file"> 设置基础上传和格式限制
HTML 原生 <input type="file"> 就能实现文件选择,但「格式限制」仅靠 accept 属性是前端提示,不是强制拦截——用户仍可手动绕过选择不合规文件。所以必须配合后续校验。
-
accept写 MIME 类型更可靠,比如accept="image/png,image/jpeg"比accept=".png,.jpg"兼容性更好(尤其 Safari 对扩展名支持弱) - 多文件上传加
multiple属性,但注意accept仍只作用于单个文件的类型判断 -
capture可触发原生相机/麦克风(如capture="camera"),但它会覆盖accept的部分行为,慎用
JavaScript 拦截非法文件:检查 file.type 和 file.name
file.type 来自浏览器对文件头的解析,可能为空或不可靠(比如 txt 文件被改成 .jpg 后缀,type 仍是 text/plain);file.name 则只看扩展名,易伪造。两者都得检查,且要互补。
- 先用
file.type过滤常见类型:if (!["image/jpeg", "image/png"].includes(file.type)) - 再 fallback 到扩展名:
const ext = file.name.split(".").pop().toLowerCase(); if (!["jpg", "jpeg", "png"].includes(ext)) - 大小限制用
file.size(单位字节),比如if (file.size > 5 * 1024 * 1024)限制 5MB - 校验失败后,清空 input 的值:
inputEl.value = "",否则重复触发 change 事件时不会再次进入回调
提交前二次校验:为什么不能只信前端 accept
前端所有限制(accept、JS 校验)都可被禁用 DevTools 或直接发请求绕过。服务端必须做完全相同的校验逻辑,包括 MIME 类型检测(用文件头而非扩展名)、实际尺寸、甚至内容合法性(如图片是否真能解码)。
使用 Puppeteer + Chrome 将 HTML 渲染为中文 PDF,自动处理图表等待、Tab 展开、动画、测高、白边消除、防分页,适用于看板、报表、网页和交互图表转 PDF。
- Node.js 中可用
file-type库读取 buffer 前若干字节识别真实类型 - Python Flask 可用
python-magic替代request.files["file"].content_type(后者仅依赖 header,易伪造) - 即使前端已限制 PNG/JPEG,服务端也要拒绝
image/gif或伪装成图片的 HTML 文件(防范 XSS)
常见报错与调试线索
上传失败时,别急着改前端——先确认错误源头在哪儿。Chrome 控制台 Network 标签下看响应状态码和返回体最直接。
-
413 Payload Too Large:Nginx 默认限制 1MB,需调client_max_body_size;Express 需设limit选项(如express.json({ limit: "10mb" })) -
400 Bad Request且 body 为空:可能是 multipart 解析失败,检查form-databoundary 是否被破坏,或后端没配好 multer / form-data 中间件 - 选完文件没反应:检查是否漏了
event.preventDefault()在表单 submit 里,或 JS 绑定的change事件监听器没生效(比如 DOM 加载时机不对)
真实项目里,格式限制的边界情况比想象中多:iOS 上拍照生成的 HEIC 文件、Windows 用户习惯用长路径+中文文件名、用户把 PDF 改后缀当图片传……这些全得在前后端留出明确错误提示,而不是静默失败。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










