为什么大文件上传成功了,却没人收到?

为什么大文件上传成功了,却没人收到?

事情是从产品团队反馈开始的:“用户上传 80MB 的视频,页面提示‘上传成功’,但后台查不到文件。”

我们立刻检查前端代码:

const res = await fetch('/api/upload', {

method: 'POST',

body: formData

});

if (res.ok) {

showSuccess("上传成功!");

} 逻辑没问题。 再看浏览器 Network 面板:

请求状态码:200 OK; Response Body:{"code":0,"msg":"success"}。 看起来真成功了。

但查后端日志——根本没有 /api/upload 的访问记录!

更诡异的是:

上传 10MB 文件,一切正常; 上传 50MB 以上,就“假成功”。 而且不是所有环境都这样:

本地开发(直接连 Spring Boot):80MB 能传; 测试环境(走 Nginx Ingress):80MB 假成功。 怀疑是不是 Nginx 拦截了? 查 Nginx Ingress Controller 日志,发现一行警告:

2024/12/10 14:23:01 [warn] 42#42: *1234 a client request body is buffered to a temporary file ... 接着是:

2024/12/10 14:23:05 [error] 42#42: *1234 client intended to send too large body: 83886080 bytes client intended to send too large body!

原来,Nginx 默认限制客户端请求体大小为 1MB(client_max_body_size 默认值)。

当请求超过这个值,Nginx 不会转发给后端,而是自己返回一个错误页面。

但为什么前端收到的是 200?

因为我们的 Nginx Ingress 配了自定义 error page:

nginx.ingress.kubernetes.io/custom-http-errors: "413"

nginx.ingress.kubernetes.io/default-backend: my-error-page-service 而那个 my-error-page-service 是个静态服务,对所有错误都返回 200 + JSON 格式的友好提示,比如:

{"code":0,"msg":"success"} ……只是为了“不让用户看到丑陋的 413”。

结果,前端把错误当成了成功。

为什么本地能传? 因为本地开发时,我们直接访问 http://localhost:8080, 绕过了 Nginx,只受 Spring Boot 限制。

而 Spring Boot 默认的 spring.servlet.multipart.max-file-size 是 1MB, 但我们在 application.yml 里显式改成了:

spring:

servlet:

multipart:

max-file-size: 100MB

max-request-size: 100MB 所以本地能传 80MB。

但 Nginx 层没配,依然卡在 1MB。

验证 用 curl 直接打 Nginx:

curl -F "file=@large-video.mp4" https://test-env/api/upload 返回:

{"code":0,"msg":"success"} 但抓包发现,这是 Nginx 返回的,不是后端。

再看响应头:

Server: nginx 确认了。

解决办法 在 Ingress 上加注解,调大 body 限制:

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: upload-ingress

annotations:

nginx.ingress.kubernetes.io/proxy-body-size: "100m"

spec:

rules:

- host: test.myapp.com

http:

paths:

- path: /api/upload

pathType: Prefix

backend:

service:

name: app-service

port:

number: 8080 注意:要用 proxy-body-size,它会设置 client_max_body_size。

同时,确保后端 Spring Boot 的 multipart 限制 ≥ Nginx 的值。

上线后,80MB 文件上传真实成功。

其实这个问题最讽刺的地方在于: 我们为了用户体验,把错误包装成成功,结果反而让用户以为功能正常,耽误了问题上报。

后来 我们做了两件事彻底避免这类问题:

统一错误响应格式,绝不让 4xx/5xx 返回 200 修改 my-error-page-service,对 413 返回:

{"code":413,"msg":"File too large"} 并让前端根据 code 判断,而不是只看 HTTP 状态码。

在 CI/CD 中加入配置一致性检查 写脚本自动比对:

Nginx proxy-body-size Spring Boot multipart.max-file-size 前端上传组件的 maxSize 三者必须一致,否则构建失败。

相关新闻

央视视频如何下载(央视纪录片如何下载)
365体育投注一直进不去

央视视频如何下载(央视纪录片如何下载)

🕒 09-28 👽 7705
qq怎么知道共同好友是谁
365体育投注一直进不去

qq怎么知道共同好友是谁

🕒 01-14 👽 3339
婚宴怎么算人数?
365体育投注一直进不去

婚宴怎么算人数?

🕒 11-03 👽 6104
魔兽世界9.2猎人橙装部位推荐
Bet体育365提款要多久2022

魔兽世界9.2猎人橙装部位推荐

🕒 07-21 👽 5210
方舟生存进化中如何制作汽油 ▷➡️
365bet手机投注网

方舟生存进化中如何制作汽油 ▷➡️

🕒 02-03 👽 1372
我们研究了四万对情侣,专门研究他们“吵架”的情况