SpringBoot项目跨服务器部署后AWS S3文件上传失败如何解决?
问题根因
- 你遇到的
FileNotFoundException: sample.txt (Permission denied)报错并非S3权限问题,根源在你代码的临时文件创建逻辑:convertMultiPartToFile方法直接在应用进程当前工作目录创建文件,而部署环境下Spring Boot的运行用户对该目录无写入权限,本地运行时你有对应目录权限所以没有触发问题。 - 「后端能收到请求但无文件」是UI层反向代理配置问题:反向代理默认会限制multipart/form-data类型的请求体,或未配置文件大小上限,导致文件内容被截断丢弃,仅普通请求参数能透传到后端。
最优解决方案(无需修改现有架构,无需UI存储文件)
直接修复现有代码和代理配置即可解决问题,成本最低:
- 优化S3上传逻辑,完全避免本地磁盘写入,从根源消除权限问题:
删掉convertMultiPartToFile方法,直接用MultipartFile的输入流上传到S3,无需落地磁盘:
如果确实需要临时存储文件,使用系统临时目录创建文件:s3ClientBuilder.build().putObject( new PutObjectRequest(s3BucketName, fileName, uploadedFile.getInputStream(), null) );// 系统临时目录默认所有进程都有读写权限 File convFile = File.createTempFile("upload_", "_" + file.getOriginalFilename()); convFile.deleteOnExit(); // 程序退出时自动清理临时文件 - 修复UI层反向代理配置,以Nginx为例,增加以下配置允许文件透传:
配置完成后文件即可正常透传到后端Controller,原有业务逻辑无需调整即可正常运行。client_max_body_size 100M; # 按你业务允许的最大文件大小调整 proxy_set_header Content-Type $content_type; proxy_request_buffering off; # 大文件场景关闭缓冲,避免超时
如果你坚持采用UI存储文件的方案实现方式
方案可行性说明
该方案可以实现,但会增加架构复杂度,需要额外处理文件同步、失败重试、本地磁盘容量管理等问题。
具体实现
不需要编写独立定时脚本,有两种可选实现路径:
- 同步实现:UI服务收到用户上传的文件后,先存储到本地临时目录,直接在UI服务代码中调用S3 SDK上传文件,上传完成后再发请求给Elastic Beanstalk存储元数据,上传成功后删除本地临时文件即可。
- 异步实现:如果文件较大不想阻塞用户请求,可以在UI服务中新增异步任务逻辑,收到文件后先返回用户上传成功的响应,后台异步执行S3上传、元数据同步、本地文件清理的逻辑。如果要用独立脚本触发,可以配置cron定时任务,每分钟扫描一次临时目录,上传未同步的文件即可,需要额外处理重复上传、上传失败重试的逻辑,非必要不建议使用。
内容的提问来源于stack exchange,提问作者arj
相关产品推荐
相关产品推荐

