SpringBoot 文件上传下载是我们常用的功能,比如图片、视频上传、下载和更新等功能的实现。下面我们详细分析一下:
1、pom.xml包引入
<!-- 基础 web 依赖(包含文件上传支持) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 文件操作工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
2、存储目录设计
/data/project_files/
├── images/
│ ├── 202405/
│ └── 202406/
└── videos/
├── 202405/
└── 202406/
- 使用
UUID
生成唯一文件名(保留原始扩展名) - 按年月生成子目录(防止单目录文件过多)
- 推荐存储绝对路径到数据库(如:
/images/202405/uuid123.jpg
)
3、配置文件信息
# win环境文件存储根目录
file.upload-dir=D:/data/project_files/
#linux环境
file.upload-dir=/data/project_files/
# 上传大小限制(默认1MB,按需调整)
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
4、上传接口
@PostMapping("/upload")
public ApiResult uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam String fileType) throws IOException {
// 验证文件类型
if (!Arrays.asList("image", "video").contains(fileType)) {
return ApiResult.error("Invalid file type");
}
// 生成存储路径
String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
String fileExt = FilenameUtils.getExtension(file.getOriginalFilename());
String uuid = UUID.randomUUID().toString();
String relativePath = String.format("/%s/%s/%s.%s",
fileType + "s", datePath, uuid, fileExt);
// 保存文件
File dest = new File(uploadDir + relativePath);
FileUtils.forceMkdirParent(dest);
file.transferTo(dest);
return ApiResult.ok(relativePath);
}
直接获取下载地址上传方式
@PostMapping("/uploadFile")
@ApiOperation(value="文件上传",notes = "文件上传-√")
public String uploadFile(@RequestParam("file")MultipartFile file, @RequestParam String fileType) throws IOException {
// 验证文件类型
if (!Arrays.asList("image", "video").contains(fileType)) {
return CommonResponse.buildErrorResponse("Error file type");
}
// 生成存储路径
String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
String fileExt = FilenameUtils.getExtension(file.getOriginalFilename());
String uuid = UUID.randomUUID().toString();
String relativePath = String.format("/%s/%s/%s.%s",
fileType + "s", datePath, uuid, fileExt);
// 保存文件
File dest = new File(uploadDir + relativePath);
FileUtils.forceMkdirParent(dest);
file.transferTo(dest);
log.info("filePath:{}",fileIpPortUrl+relativePath);
return (fileIpPortUrl+relativePath);
}
5、下载接口
1)接口下载
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile(@RequestParam String filePath) throws IOException {
Path path = Paths.get(uploadDir + filePath);
Resource resource = new UrlResource(path.toUri());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
2)原路径获取下载
@GetMapping("/download/**")
@ApiOperation(value="文件下载接口",notes = "文件下载接口-√")
public ResponseEntity<Resource> downloadFile(HttpServletRequest request) throws IOException {
// 获取完整文件路径(需截掉前缀路径)
String filePath = request.getServletPath()
.replaceFirst("/file/******/", "");
log.info("filePath:{}",filePath);
// 路径安全校验
if (filePath.contains("..")) {
return ResponseEntity.badRequest().build();
}
Path path = Paths.get(uploadDir + File.separator + filePath);
log.info("path:{}",path);
Resource resource = new UrlResource(path.toUri());
log.info("toUri:{}",path.toUri());
if (!resource.exists()) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
6、修改文件
@PostMapping("/update")
public ApiResult updateFile(@RequestParam("file") MultipartFile file,
@RequestParam String oldFilePath) throws IOException {
// 删除旧文件
File oldFile = new File(uploadDir + oldFilePath);
if (oldFile.exists()) {
FileUtils.forceDelete(oldFile);
}
// 上传新文件(复用上传逻辑)
return uploadFile(file, parseFileType(oldFilePath));
}
或者
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.UUID;
@PostMapping("/update")
public String updateFile(@RequestParam("file") MultipartFile file,
@RequestParam String oldFilePath, @RequestParam String fileType) throws IOException {
// 删除旧文件
File oldFile = new File(uploadDir + oldFilePath);
if (oldFile.exists()) {
FileUtils.forceDelete(oldFile);
}
// 上传新文件(复用上传逻辑)
return uploadFile(file, fileType);
}
到此,文件上传下载分享完成,后期会分享站点上传数据,敬请期待。