input type="file" 的 change 事件第二次选择同一文件不触发,是因为其 value 未改变;解决方法是在每次处理完文件后将 input.value 设为空字符串,确保下次选择时 value 发生变化从而触发事件。

直接用 fetch 或 XMLHttpRequest 配合 FormData 就能上传,不需要表单提交刷新页面。关键不是“能不能”,而是“怎么传得稳、不丢、有反馈”。
input type="file" 的 change 事件拿不到文件?
常见现象:点了选择、选了文件,但 e.target.files 是空的或长度为 0。
- 检查是否漏了
multiple属性却试图读取多个文件 —— 单选时只认files[0],没选就是undefined -
accept写错 MIME 类型(比如写成jpg而不是image/jpeg)会导致浏览器过滤掉合法文件 - 别在表单 submit 里直接读
files,因为表单可能被默认提交并跳转;改用change事件监听更可靠 - 移动端某些 WebView(如旧版微信内置浏览器)对
capture+accept组合支持不稳定,建议降级 fallback 到纯type="file"
FormData.append() 传文件时字段名对不上后端?
后端报错类似 Missing part 'file' 或解析出空文件,大概率是 append 的第一个参数(字段名)和后端约定不一致。
- 常见后端接收字段名有:
file、uploaded_file、myfile、files[](PHP 多文件),必须和后端文档/接口定义完全一致 - 多文件上传别用循环反复
append('file', file)—— 这会覆盖,应该用append('files', file)(单字段多值)或带索引的键名如append('files[0]', file) - 如果后端要求带额外字段(如
user_id、token),也得一起append进去,顺序无关,但不能漏 - 不要手动设置
Content-Type请求头 ——FormData交给fetch或XHR发送时,浏览器会自动设为multipart/form-data; boundary=...,手设反而会破坏边界分隔
上传大文件卡死或进度条不动?
上传几 MB 以上文件时,progress 事件不触发、请求超时、甚至整个页面假死。
立即学习“前端免费学习笔记(深入)”;
-
XMLHttpRequest的upload.onprogress只对上传阶段有效,且必须在xhr.open()之后、xhr.send()之前绑定 -
fetch原生不支持上传进度 —— 想监控就得切回XMLHttpRequest,或者用ReadableStream+TransformStream手动分块(复杂度高,一般不推荐) - 服务端 Nginx/Apache 默认限制上传大小(如 Nginx 的
client_max_body_size 1m),前端再怎么传,到网关就被截断,需同步调大 - Chrome 对超大
File对象(>2GB)可能触发内存警告,建议前端加if (file.size > 500 * 1024 * 1024)提前拦截并提示
最易被忽略的是:后端返回的响应体内容类型(Content-Type)若不是 application/json,而你又写了 .json() 解析,就会静默失败。上传完成后的处理逻辑,得先看 response.headers.get('content-type') 再决定怎么读取 body。



















