accept属性仅作前端提示,无法真正限制文件类型;必须写成accept=".html,.htm,text/html"(逗号无空格),并配合前端校验file.name后缀及后端基于文件头(magic bytes)的最终校验。

怎么用 accept 属性限制 HTML 文件选择
只允许用户选 .html 或 .htm 文件,accept 必须写成 accept=".html,.htm" —— 缺少点号(比如写成 accept="html,htm")就完全失效。部分浏览器对 text/html MIME 类型支持不稳定,尤其 Windows 和移动端 Safari,所以别依赖它,更不能只写 accept="text/html"。实际项目中建议双保险:accept=".html,.htm,text/html",逗号分隔、无空格。
input.files[0].type 和 .name 哪个更靠谱
input.files[0].type 是浏览器推测的 MIME 类型,经常为空或不准(比如拖拽上传时返回空字符串,或把 .html 错报成 text/plain)。真正能稳定取到扩展名的是 input.files[0].name:
- 用
file.name.split('.').pop().toLowerCase()提取后缀 - 注意:用户可能传
index.HTML或README(无后缀),得兜底处理 - 仅用于前端提示,绝不能当真实类型依据——后缀可伪造,
evil.php改成safe.html就能绕过
为什么后端必须读文件头(magic bytes)
靠扩展名或 Content-Type 头校验 HTML 文件极不安全。攻击者上传一个伪装成 HTML 的 PHP 文件,只要改后缀、改 header,就能骗过大多数前端+后端检查。真实判断方式是读文件前若干字节:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 标准 HTML 文件开头通常是
或 <code>,但首行可能有 BOM 或空白,不能简单 <code>startsWith - 更可靠的是用魔数库(如 Node.js 的
file-type)读 buffer 前 12 字节,它会比对已知 HTML 签名(如/code> 的 UTF-8 编码序列) - PHP 推荐用
finfo_open(FILEINFO_MIME_TYPE)+finfo_file(),别信$_FILES['file']['type'] - Spring Boot 别调
MultipartFile.getContentType(),改用Files.probeContentType()或 Apache Tika
enctype="multipart/form-data" 漏了会怎样
表单没设 enctype="multipart/form-data",哪怕 <input type="file"> 存在,后端也收不到任何文件字段——req.files 为空、$_FILES 为空数组、MultipartFile 为 null,且通常不报错,容易卡在前端排查 JS 逻辑。必须显式声明:
<form method="POST" enctype="multipart/form-data"></form>- 如果用
fetch+FormData,这步由浏览器自动处理,无需手动设 header - 但若手写
XMLHttpRequest并手动拼 body,漏掉boundary或错设Content-Type,服务端同样解析失败
真正难的不是识别 HTML 后缀,而是确认那是个合法、未篡改、不含可执行脚本的真实 HTML 文件——所有前端检查都只是减少无效请求,最后一道防线永远在服务端读取原始字节并拒绝非 HTML 魔数的输入。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










