图片上传进度条卡住,多数情况不是网速差,而是”一次性整包上传”的老架构撞上了网关体积限制、连接超时和缺失的断点续传;换成浏览器端分片直传、把超时和重试补齐,供应商后台的抱怨通常当天就能压下去。
进度条停在某个百分比,卡的是哪一层
供应商在后台点”批量上传”,几十张商品图排队往上走,进度条爬到八成突然不动,转圈转到人失去耐心,最后弹一句”上传失败”,这种画面在2026年依然常见,因为它从来不是单一故障,而是好几层超时叠在一起。
浏览器、网关、后端,三处超时各管一段
一次图片上传要穿过三段链路,每一段都有自己的耐心上限:
- 浏览器到网关:请求体还没发完,网关已经判定”太慢”,直接断连,前端只能拿到一个失败的
xhr。 - 网关到应用:据Nginx官方文档,
proxy_read_timeout默认是60秒,超过就切断上游连接,批量传图时后端排队处理,很容易踩线。 - 应用存储:对象存储的分片上传如果某一片迟迟收不到完成信号,任务会挂起,前端进度条自然定格。
任何一段先放弃,用户看到的现象都一样进度条卡住。
整包上传的三个死穴
行业共识认为,大文件上传的稳定性取决于”能否失败后只重传一小段”,而整包上传在这件事上毫无余地:
- 体积天花板:Nginx 的
client_max_body_size默认只有 1m,不调整的话,稍大的图片直接返回 413,前端连进度条都不该有,却常常因为错误处理缺失而显示”卡住”。 - 断点即归零:传到90%断网,重来一次从0%开始,供应商的网络环境参差不齐,这个损耗被放大得很明显。
- 内存压力:服务端中转模式下,请求体和临时文件同时占内存,并发一高就开始互相拖累。
前端进度条本身也会”骗人”
xhr.upload.onprogress 上报的是”浏览器把数据交给内核缓冲区”的进度,不是”服务器已收到”的进度,最后一段数据堆积在缓冲区等待发送时,事件不再触发,进度条就僵在99%附近,相当一部分”卡住”投诉,实际是上传已经成功、界面没更新,判断方法很简单:打开开发者工具的 Network 面板,看这条请求最终返回的是200还是超时。
供应商后台图片上传进度条卡住怎么办:四步定位法
别急着改代码,先按顺序把故障层锁死,能省下大量无效返工。
第一步:看请求断在哪一段
- 打开浏览器开发者工具,切到 Network,筛
Fetch/XHR。 - 观察状态:长时间
Pending说明连接没建立或网关在等;Upload阶段数值不动说明发送受阻;直接413是体积超限;504是网关等后端超时。 - 用命令行复现一次,绕开前端干扰:
curl -v -F "file=@test-20m.jpg" https://供应商后台域名/api/upload
能看到具体状态码和响应头,比猜快得多。
第二步:核对体积限制
- 检查网关配置里的
client_max_body_size,按业务最大图片体积的1.5倍设置。 - 检查应用框架自身的上传体积上限,Spring 系的
max-file-size、max-request-size都要同步放开。 - 检查对象存储侧对单次请求的限制。
第三步:拉长超时链路
网关侧建议同步调整:
client_max_body_size 20m;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
后端 HTTP 客户端的连接超时、读取超时要大于网关值,否则内层先断,外层还在傻等。
第四步:查存储回调与鉴权
分片上传的最后一步是”合并分片”,这一步如果签名过期、回调地址不可达,前端就会一直等合并结果,查看存储服务端的任务列表,多数控制台都能看到挂起的 multipart 任务,这是最直接的证据。
分片上传和直传哪个更稳定:三种方案横向对比
改造之前先把方案选对,选错了后面全是补丁。
| 方案 | 稳定性 | 断点续传 | 服务端压力 | 改造成本 | 适用场景 |
|---|---|---|---|---|---|
| 表单整包直传 | 一般,大图易失败 | 不支持 | 低 | 最低 | 小图为主、单张上传 |
| 服务端中转 | 一般,受应用内存制约 | 需自行实现 | 高 | 中等 | 需要强校验、强审计 |
| 前端分片直传 | 较高,单片刻度重试 | 原生支持 | 低 | 中等偏上 | 供应商批量传图 |
按对象存储服务的公开文档,分片上传的单片大小最小为5MB(最后一片除外),单片上限可达数GB,分片数量有上万片的上限,这些参数决定了你的分片策略。
分片参数怎么定才不踩坑
- 分片大小:单张商品图常见在2MB到10MB之间,固定5MB分片反而会让小图多出一次请求开销,建议按文件体积动态切:小于10MB整包传,10MB到100MB用5MB分片,更大的用10MB分片。
- 并发数:3到5路足够,并发太高会挤占供应商本就有限的出口带宽,整体耗时反而变长。
- 重试策略:单分片失败后按1秒、2秒、4秒指数退避重试三次,仍失败才整体报错,并在界面上明确提示”第X片重试中”。
- 进度计算:用”已完成分片字节数 ÷ 总字节数”,不要用单个请求的
onprogress,这样进度条才不会在合并阶段僵住。
对象存储分片上传改造大概多少钱
这是采购和运维最关心的问题,答案取决于改造范围,而不是某个固定报价。
- 纯前端改造:不新增服务端逻辑,只把直传换成前端切片加临时凭证,投入通常在几个人日到两三周之间,视现有上传组件成熟度浮动。
- 需要后端签发临时凭证:多一个签名接口和权限收敛,工时增加有限,但安全收益明显,避免长期密钥写进前端。
- 流量与存储费用:对象存储按量计费,分片上传本身不会显著增加流量,但失败重传会,业内专家指出,把客户端压缩和格式转换前置,往往比优化上传链路更能省钱一张原图压到WebP,体积能降下相当一部分,供应商等待时间同步缩短。
- 隐性成本:跨地域回源、CDN刷新、图片处理次数,这些在上量之后才会显现,做预算时别只看存储单价。
跨地域供应商批量上传图片慢,先排除这三处
供应商分布在不同地区,同样的后台在有的地方顺畅、有的地方卡顿,多半不是代码问题:
- DNS解析绕路:跨网访问时解析到了远端节点,首包延迟被拉长。
- 上传域名未就近接入:对象存储的上传端点建议按地域就近配置,而不是全量指向单一区域。
- 运营商出口拥塞:晚间高峰时段尤为明显,可通过并发限流和错峰提示缓解。
排障之外,界面本身也该改
进度条卡住引发抱怨,一半是技术故障,一半是信息不透明,用户在等待时最怕”不知道发生了什么”。
- 进度条旁边显示实时速率和剩余时间估算,哪怕不准,也比静止强。
- 分片重试时给出明确文案,而不是让进度条回退。
- 失败后保留已上传分片,提供”继续上传”按钮,而不是逼用户从头再来。
- 批量上传时逐张显示状态,一张失败不影响其余,避免整批回滚。
这几条改动量不大,但对投诉量的抑制效果,往往超过底层优化本身。
关于图片上传进度条卡住的常见疑问
问:为什么小图从来不卡,稍微大一点的图必卡?
答:这是典型的体积阈值问题,小于网关 client_max_body_size 的文件一次通过,超过就被拦截或长时间等待;同时大文件传输时间更长,更容易撞上60秒的读取超时,两个限制叠加,就形成了”小图没事、大图必挂”的规律。
问:进度条卡在99%不动,是不是上传其实已经成功了?
答:有这个可能,浏览器上报的是写入发送缓冲区的进度,最后一段数据在缓冲区等待期间不再触发进度事件,此时应看 Network 面板里该请求的最终状态码,200即代表服务端已接收,问题出在前端没有正确结束状态;如果一直 Pending 到超时,则是网关或后端仍在处理。
问:改成前端分片直传后,供应商的流量消耗会变多吗?
答:正常情况下不会,分片只改变传输方式,不改变总字节数;额外开销来自每片的请求头和签名,占比很小,真正增加流量的是失败重传,而分片恰恰把重传范围从整个文件缩小到单个分片,总体流量通常下降。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/%e4%b8%ba%e4%bb%80%e4%b9%88%e5%9b%be%e7%89%87%e4%b8%8a%e4%bc%a0%e8%bf%9b%e5%ba%a6%e6%9d%a1%e6%80%bb%e5%8d%a1%e4%bd%8f%ef%bc%8c%e4%be%9b%e5%ba%94%e5%95%86%e5%90%8e%e5%8f%b0%e6%8a%b1%e6%80%a8%e4%b8%8d/


