SpringBoot 文件上传(详细步骤+图解)--废话少说,直接上步骤。
最编程
2024-05-01 20:40:49
...
- 先上数据库脚本(注:MySQL)
CREATE TABLE `file` (
`id` bigint(225) NOT NULL AUTO_INCREMENT COMMENT '文件ID',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名',
`suffix` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件类型',
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件相对路径',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1942 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '文件表' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
- 在项目的yml文件中配置好上传路径和读取路径(上传服务器改下路径打包就可以了)
file:
#上传路径
path: d:/file/
access:
base-url:
#访问路径
file: d:/file/
- 封装实体类
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class File implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 文件ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 文件名
*/
private String name;
/**
* 文件类型
*/
private String suffix;
/**
* 文件相对路径
*/
private String path;
/**
* 文件原名字
*/
@TableField(exist = false)
private String oldName;
}
- 创建文件返回视图类
@Data
@ApiModel("文件")
public class FileVO {
@ApiModelProperty(value = "文件ID")
private Long id;
@ApiModelProperty(value = "源文件名")
private String oldName;
@ApiModelProperty(value = "现文件名")
private String name;
@ApiModelProperty(value = "文件类型")
private String suffix;
@ApiModelProperty(value = "访问地址")
private String url;
}
- 编写文件上传Controller类
@Slf4j
@RestController
@Api(tags = "文件上传接口")
@RequestMapping("/file")
public class FileController {
@Resource
private FileService fileService;
@ApiOperation("根据id查询单个")
@GetMapping("/getById")
public R getById(Integer id) {
return R.ok(fileService.getVOById(id));
}
@ApiOperation("文件单个上传")
@PostMapping("/uploadByOne")
public R uploadByOne(@RequestParam("file") MultipartFile file) {
try (InputStream is = file.getInputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
IOUtils.copy(is, os);
byte[] bytes = os.toByteArray();
FileVO vo = fileService.storeFile(bytes, file.getOriginalFilename());
return R.ok(vo);
} catch (IOException e) {
log.error("文件上传发生异常 -> {}", e.getMessage());
return R.failed("文件上传失败");
}
}
}
- 编写Service接口
public interface FileService extends IService<File> {
/**
* 根据ID获取视图对象
* @param id
* @return
*/
FileVO getVOById(Integer id);
/**
* 文件上传
* @param content
* @param originFileName
* @return
*/
FileVO storeFile(byte[] content, String originFileName);
/**
* 存储文件到本地
* @param content
* @param path
* @param fileName
*/
void storeFileWithFileName(byte[] content, String path, String fileName);
}
- 编写Service接口实现类
@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements FileService {
@Value("${file.path}")
private String FILE_PATH;
@Value("${access.base-url.file}")
private String ACCESS_BASE_URL;
private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
@Override
public FileVO getVOById(Integer id) {
if (id != null) {
File file = this.getById(id);
if (file != null) {
FileVO result = BeanUtil.toBean(file, FileVO.class);
result.setUrl(genAccessUrl(file.getPath(), file.getName()));
return result;
}
}
return null;
}
@Override
public FileVO storeFile(byte[] content, String originFileName) {
// 获取文件后缀 生成目录路径
// 配置文件里的file.path + yyyyMMdd 格式组成文件夹路径
String folder = LocalDateTime.now().format(dateTimeFormatter);
String suffix = originFileName.substring(originFileName.lastIndexOf(".")),
filePath = FILE_PATH + folder + java.io.File.separatorChar;
// 保存文件并返回文件名
String fileName = this.storeFile(content, filePath, suffix);
// 入库
File file = new File();
file.setName(fileName);
file.setSuffix(suffix);
file.setPath(folder);
file.setOldName(originFileName);
baseMapper.insert(file);
FileVO result = BeanUtil.toBean(file, FileVO.class);
result.setUrl(genAccessUrl(folder, fileName));
result.setId(file.getId());
return result;
}
@Override
public void storeFileWithFileName(byte[] content, String path, String fileName) {
// 目录不存在则创建
java.io.File file = new java.io.File(path);
if (!file.exists()) {
file.mkdirs();
}
try (FileOutputStream os = new FileOutputStream(path + fileName);
ByteArrayInputStream is = new ByteArrayInputStream(content)) {
IOUtils.copy(is, os);
} catch (IOException e) {
log.error("存储文件到本地时发生异常:{}", e);
}
}
private String storeFile(byte[] content, String path, String suffix) {
String fileName = generateFileName(suffix);
storeFileWithFileName(content, path, fileName);
return fileName;
}
private String generateFileName(String suffix) {
return generateFileName() + suffix;
}
private String genAccessUrl(String folder, String name) {
return ACCESS_BASE_URL + folder + "/" + name;
}
private String generateFileName() {
return System.currentTimeMillis() + "_" + RandomUtil.randomNumbers(6);
}
}
- 使用Swagger进行测试
上传文件 查询文件
注:此demo使用了Lombok插件,在线接口文档Swagger,持久层框架MyBatis-Plus,详情见下列文章:
个人总结在平时工作用的比较多的一些Lombok注解(详解) SpringBoot集成Swagger3--在线API文档(详细步骤+图解) SpringBoot集成MyBatis-Plus以及MyBatis-Plus代码生成工具类(详细步骤+图解)