原生 是 html 文件上传的唯一必需起点,需配合 formdata 和 fetch(post)手动上传,注意字段名匹配、禁设 content-type、服务端解析配置及文件头校验。

HTML 文件上传用 <input type="file"> 就够了
不需要额外库、不依赖框架,原生 <input type="file"> 是唯一必须的起点。它本身不发请求,只负责选文件;后续上传动作(比如用 fetch 或 XMLHttpRequest)得自己写。
常见错误是以为加个 form + submit 就算“实现上传”——其实只是触发了浏览器默认表单提交,服务端收不到结构化数据,前端也难控制进度、校验或取消。
-
accept属性要写对,比如只允许 HTML 文件:accept=".html,.htm"(注意点不能少,text/html在部分浏览器不生效) - 必须加
multiple才能多选,否则每次只能挑一个 -
capture在移动端会强制调用摄像头 / 相册,和 HTML 文件无关,别乱加
用 fetch 上传 HTML 文件要构造 FormData
直接把 File 对象扔给 fetch 会报错:TypeError: Request with GET/HEAD method cannot have body —— 因为没指定方法,或没包装成可发送格式。
正确路径是:监听 input 的 change 事件 → 取出 files[0] → 塞进 FormData → 用 POST 发出去。
立即学习 “ 前端免费学习笔记(深入)”;
const input = document.querySelector('input[type="file"]'); input.addEventListener('change', async (e) => {const file = e.target.files[0]; if (!file) return; const formData = new FormData(); formData.append('html_file', file); // 字段名要和服务端约定一致 try {await fetch('/upload', { method: 'POST', body: formData}); } catch (err) {console.error('上传失败:', err); } });
服务端收不到文件?检查 Content-Type 和字段名
用 FormData 提交时,浏览器自动设置 Content-Type: multipart/form-data; boundary=……,你 ** 绝不能手动设置这个 header**,否则后端解析器会直接丢弃 body。
Node.js(Express)常见坑:req.body 永远为空,因为文件不在 body 里,在 req.files(需用 multer)或原始流中;Python Flask 默认也不处理 multipart,得用 request.files.get('html_file'),字段名必须和前端 formData.append() 里的第一个参数完全一致。
- 字段名大小写敏感,
'Html_File'和'html_file'是两个东西 - 如果服务端返回
400 Bad Request且日志提示“no file part”,大概率是字段名不匹配 - Nginx 默认限制上传大小(通常是 1MB),传大一点的 HTML(比如含 base64 图片)会静默失败,需调
client_max_body_size
上传前校验 HTML 文件内容比扩展名更可靠
仅靠 accept=".html" 或检查 file.name.endsWith('.html') 很容易绕过——用户改个后缀就能上传任意二进制文件。
真要防误传,读取文件头几个字节判断是否含 /code> 或 <code> 更实在,但注意:小文件可以全读,大文件建议只读前 2KB。
const reader = new FileReader(); reader.onload = (e) => {const content = e.target.result.substring(0, 2048); if (!/<html|!doctype/i.test(content)) {alert('这不是有效的 HTML 文件'); return; } // 继续上传 }; reader.readAsText(file);
这步容易被跳过,尤其在内部工具里——结果某天有人上传了 report.pdf 改名成 index.html,服务端解析失败,又查不出原因。






























