游客发表
浏览器上传文件时弹出“网络错误”或“请求失败”,通知十有八九不是浏览服务器挂了,而是器上前端把请求体搞成了非法格式。上周我们运维同事处理过一个案例:用户用Chrome上传一个2.3GB的传文出现压缩包,进度条卡在99%然后直接报错。异常查了半天,通知nginx日志里连个POST记录都没有——请求压根没到后端。浏览
问题出在浏览器对上传请求的器上预检(preflight)机制上。如果你用axios或者fetch上传文件,传文出现且没有显式设置Content-Type为multipart/form-data,异常浏览器会先发一个OPTIONS请求去探路。通知一旦服务器没正确响应CORS头,浏览整个上传流程直接中断。器上那个2.3GB的传文出现包,就是异常卡在OPTIONS阶段,浏览器等不到服务器的“允许”信号,干脆自己掐断了连接。
更隐蔽的坑在文件大小上。很多前端工程师以为设置了timeout: 30000就万事大吉,但上传大文件时,真正卡住的是请求体发送阶段。浏览器在发送大文件时,如果网络抖动导致TCP窗口收缩,进度条可能停在某个百分比不动,这时候如果触发了浏览器的“空闲超时”机制(比如Chrome的net::ERR_TIMED_OUT),就会直接报错。别迷信那些所谓“重试三次”的提示——重试时如果文件没走分片上传逻辑,照样会把整个文件重新读一遍内存,内存占用直接翻倍。
我见过最离谱的一次异常,是用户用Edge浏览器上传PDF,文件名带了个中文括号“(”。结果后端Java的CommonsMultipartResolver解析文件名时,把括号当成了正则特殊字符,直接抛异常。前端收到的报错信息是“上传失败”,但实际是后端解析器崩了。这提醒我们:排查问题时,先看浏览器Network面板里请求是否真的发出去了,再看后端日志有没有对应记录——别一上来就怀疑网络。
另一个高频原因是浏览器插件干扰。我们测试过,装了某些广告拦截插件(比如uBlock Origin)后,它会把包含multipart/form-data的POST请求误判为“跟踪脚本”,直接拦截。用户看到的现象是:上传按钮点了没反应,或者进度条走完但永远不跳转。这种问题在无痕模式下测一次就能定位——如果无痕模式正常,那就是插件干的。
最后说个冷门的:如果你用HTTP/2协议上传,且服务器配置了http2_max_concurrent_streams过低,当页面同时有多个上传任务时,新的请求会被挂起。表现就是第一个文件传完了,第二个文件一直转圈,最后报“连接重置”。这属于服务器端调优问题,但前端可以做的妥协是:把并发上传数限制在2个以内,或者改用分片顺序上传。
遇到上传异常,别急着改代码。先打开浏览器F12,看Console里有没有红色报错,再切到Network标签,筛选Fetch/XHR请求,检查那个POST请求的状态码。如果是407,说明走了代理且代理需要认证——这种情况在公司内网环境特别常见。如果是413,那是服务器限制了请求体大小,去改nginx的client_max_body_size就行。真正的疑难杂症,往往藏在响应头里——比如服务器返回了Content-Type: text/html,但你的前端代码却按JSON解析,这时候报错信息会被吞掉,只留下一个笼统的“上传失败”。
友情链接