FastAPI文件上传经API Gateway/CloudFront/NGINX路由链后出现空白/损坏问题求助
FastAPI文件上传经API Gateway/CloudFront/NGINX路由链后出现空白/损坏问题求助
兄弟,我之前也碰到过类似跨路由链的文件上传损坏问题,结合你给出的日志和测试数据,大概率是路由链上某个环节对二进制内容的处理出了问题,咱们一步步来分析和排查:
先看你给出的关键差异数据,这是定位问题的核心:
- 内部请求:FastAPI收到的文件是30176字节,NGINX日志里请求总大小30650字节,完全正常
- 外部请求:FastAPI收到的文件只剩5758字节,NGINX日志里请求总大小才1048字节,明显是内容被截断或转码损坏了
最可能的原因及对应排查/解决步骤
1. API Gateway 未配置二进制媒体类型(最可能的元凶)
API Gateway默认会把所有请求当成纯文本处理,如果你的multipart/form-data里包含二进制文件,它会强制把二进制内容转成UTF-8文本,直接导致二进制损坏、内容截断。
排查&解决:
- 登录AWS控制台,找到你的API Gateway实例,进入「Settings」页面
- 在「Binary Media Types」里添加
multipart/form-data和application/pdf(测试阶段可以临时加*/*,生产环境建议精准匹配) - 重新部署你的API,然后立即测试外部上传
2. CloudFront 压缩/转发设置异常
CloudFront如果开启了自动压缩,可能会误把二进制PDF或multipart表单当成文本压缩,导致内容损坏;另外如果没有正确转发必要请求头,后端也无法正确解析表单结构。
排查&解决:
- 进入CloudFront控制台,找到对应API的「Behaviors」规则
- 关闭「Compress Objects Automatically」(至少针对
/document/upload这个路径的独立行为) - 确认「Allowed HTTP Methods」包含POST请求
- 把「Forward Headers」设置为「AllViewer」,或至少包含
Content-Type、Content-Length、Transfer-Encoding - 保存后等待CloudFront配置生效(约10-15分钟)再测试
3. NGINX 配置仍有遗漏(虽然你调整了大小,但还有隐藏坑)
你已经调整了大文件支持,但可能还有几个关键配置没到位,导致请求转发时损坏:
建议修改NGINX的location配置块为:
location /document/upload { client_max_body_size 100M; # 确保足够覆盖你的文件+表单总大小 proxy_request_buffering off; # 关闭请求缓冲,直接转发给后端,避免大文件截断 proxy_buffering off; # 关闭响应缓冲,同理 proxy_http_version 1.1; # 强制用HTTP/1.1转发,和后端FastAPI兼容 proxy_set_header Connection ""; # 配合HTTP/1.1,避免长连接头冲突 proxy_set_header Host $host; # 正确传递请求Host头 proxy_set_header X-Real-IP $remote_addr; # 可选,方便日志溯源 proxy_pass http://doc-service.default.svc.cluster.local:8500; }
临时调试技巧:
在上述location块里添加client_body_in_file_only on;,NGINX会把收到的请求体保存到/var/lib/nginx/body/目录的临时文件中:
- 如果临时文件大小和你本地的test.pdf+表单数据总大小一致,说明问题出在NGINX转发给FastAPI的环节
- 如果临时文件大小明显偏小,说明请求到达NGINX之前就已经被截断/损坏,问题出在CloudFront/API Gateway/ALB
4. ALB 请求大小限制(兜底排查)
虽然你的测试文件只有30KB,ALB默认1MB的限制应该足够,但保险起见还是检查:
- 进入AWS EC2控制台,找到你的ALB,进入「Listeners」页面编辑对应监听器
- 检查「Default action」的「Forward」配置,确认「Request body size constraint」设置足够大(比如100MB)
快速定位问题的后端调试技巧
你可以在FastAPI里加一个临时调试接口,直接验证收到的请求体是否完整:
from fastapi import FastAPI, Request app = FastAPI() # 临时调试接口,生产环境记得删除 @app.post("/debug-upload") async def debug_upload(request: Request): body = await request.body() print(f"收到的请求体总大小: {len(body)} 字节") print(f"前100字节内容: {body[:100]}") # 可选:把收到的内容保存到本地对比 with open("/tmp/debug-received.bin", "wb") as f: f.write(body) return {"received_size": len(body)}
分别用内部和外部请求调用这个接口:
- 内部调用返回的大小和本地文件+表单总大小一致 → 后端逻辑没问题
- 外部调用返回的大小明显偏小 → 请求在到达FastAPI前就已损坏
最后总结
从你的NGINX日志来看,外部请求的大小被砍到1048字节,大概率是API Gateway未配置二进制支持导致的,先从这个点入手,应该能直接解决问题。如果还不行,再按CloudFront → NGINX → ALB的顺序排查,肯定能找到问题环节!




