新上传文件无法显示/打开问题求助(Spring Boot项目)
文件上传后404问题的解决方案
问题根因
你遇到的问题本质是:Spring Boot开发模式下,src/main/resources/static目录的静态资源会被预加载到内存中,新上传的文件不会被自动扫描识别。所以刚上传完就访问会返回404,重启项目或重新登录(触发Spring上下文刷新)后,新文件才会被加载到内存,就能正常访问。
可行解决方案
方案1:将文件上传到静态资源目录外,通过Controller映射访问(推荐生产/开发通用)
这种方式彻底脱离Spring静态资源自动扫描的限制,通过自定义Controller来处理文件请求,是最稳定的方案。
步骤1:修改上传控制器的存储路径
把原来的src/main/resources/static/files-upload替换成项目外部的独立目录:
@Controller @SessionAttributes("user") public class fileController { @Autowired private fileModelRepo fileModelRepo; @PostMapping("/upload") public String handleFileUpload(@RequestParam("file") MultipartFile file, Model model) throws IOException{ UserModel user = (UserModel) model.getAttribute("user"); if (!file.isEmpty()) { try { String fileCode = RandomStringUtils.randomAlphanumeric(10); // 修改为项目外部的独立目录 String uploadDir = "D:\\restApiFileManager\\files-upload"; File uploadDirFile = new File(uploadDir); if (!uploadDirFile.exists()) { uploadDirFile.mkdirs(); } String fileName = file.getOriginalFilename(); String filePath = uploadDir + File.separator + fileCode + fileName; file.transferTo(new File(filePath)); Double sizeD = (double)file.getSize()/1024/1024; final DecimalFormat decfor = new DecimalFormat("0.00"); String size = String.valueOf(decfor.format(sizeD)) + "MB"; fileModel fileModel = new fileModel(size,fileName); fileModel.setUri(fileCode); if(user!=null) { fileModel.setUser(user); } fileModelRepo.save(fileModel); } catch (IOException e) { e.printStackTrace(); } } return "redirect:/home"; } }
步骤2:新增文件访问Controller
创建一个专门处理文件请求的Controller,负责读取外部目录的文件并返回给前端:
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import java.io.File; import java.io.IOException; import java.nio.file.Files; @Controller public class FileAccessController { // 建议将路径配置到application.properties,用@Value注入,方便后续修改 private final String UPLOAD_DIR = "D:\\restApiFileManager\\files-upload"; @GetMapping("/files/{fileCode}/{fileName}") public ResponseEntity<Resource> serveFile(@PathVariable String fileCode, @PathVariable String fileName) { try { File targetFile = new File(UPLOAD_DIR + File.separator + fileCode + fileName); Resource resource = new FileSystemResource(targetFile); if (resource.exists() && resource.isReadable()) { // 自动识别文件MIME类型 String contentType = Files.probeContentType(targetFile.toPath()); return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .body(resource); } else { return ResponseEntity.notFound().build(); } } catch (IOException e) { e.printStackTrace(); return ResponseEntity.internalServerError().build(); } } }
前端访问方式调整
前端预览或打开文件时,使用/files/${fileModel.uri}/${fileModel.fileName}作为访问路径,替代原来直接访问/files-upload/xxx的方式。
方案2:关闭静态资源缓存(仅适合开发环境)
如果只是开发阶段临时解决,可以通过配置关闭Spring Boot的静态资源缓存,让每次请求都直接读取磁盘文件:
在src/main/resources/application.properties中添加以下配置:
# 关闭静态资源缓存 spring.web.resources.chain.cache=false spring.web.resources.cache.cachecontrol.no-store=true # 显式指定静态资源位置,包含磁盘路径 spring.web.resources.static-locations=classpath:/static/,file:src/main/resources/static/
注意:此方案不适合生产环境,会严重影响静态资源的访问性能。
额外注意事项
- 生产环境中,不建议将文件存储在服务器本地,优先使用云存储(如OSS、S3)或专门的文件服务器。
- 确保上传目录的读写权限配置正确,避免出现文件写入失败或读取权限不足的问题。
内容的提问来源于stack exchange,提问作者alex kulinsky
相关产品推荐
相关产品推荐

