一、参考文档
springboot 文件MultipartFile上传路径问题 | 橙熟^ _ ^-CSDN(原本采用绝对路径,参考该文章改成相对路径)
组件 | Element
二、导入依赖和配置application.yml文件
1、在pom.xml中导入依赖。
采用了mybatis-plus,需要导入依赖。
<!-- mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
2、导入依赖配置application.yml文件。
server:
port: 8800
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/数据库名?serverTimezone=GMT%2B8
username: root
password: 123456
mybatis-plus:
# mapper扫描
mapper-locations: classpath*:mapper*.xml
configuration:
# 打印sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
files:
upload:
# 文件相对路径
path: ./src/main/resources/images/
三、创建数据库表和创建实体类
1、创建数据库files表。
DROP TABLE IF EXISTS `files`;
CREATE TABLE `files` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '文件id',
`files_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件名称',
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件类型',
`size` double(32, 2) NULL DEFAULT NULL COMMENT '文件大小(KB)',
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '下载链接',
`md5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件md5',
`enable` tinyint NULL DEFAULT 1 COMMENT '链接是否可用(1:是 0:否)',
`is_delete` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除(1:是 0:否)',
`create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
`update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `name`(`files_name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '文件表' ROW_FORMAT = Dynamic;
2、创建实体类Files。
@Data
@TableName("files")
public class Files implements Serializable {
@TableId(type = IdType.AUTO)
private Integer id;
private String filesName;
private String type;
private Double size;
private String url;
private String md5;
private Boolean enable;
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@TableLogic()
private Integer isDelete;
}
四、创建Mapper层
1、创建FilesMapper。
@Mapper
public interface FilesMapper extends BaseMapper<Files> {
}
2、创建FilesMapper.xml。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hyc.nsms.mapper.FilesMapper">
</mapper>
五、创建业务层
1、创建FilesService。
public interface FilesService extends IService<Files> {
String upload(MultipartFile file);
void download(String filesUUID, HttpServletResponse response);
}
2、创建FilesServiceImpl。
@Service
public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements FilesService {
@Value("${files.upload.path}")
private String filesUploadPath;
@Override
public String upload(MultipartFile file) {
String destPath = new File(filesUploadPath).getAbsolutePath();
String originalFilename = file.getOriginalFilename();
double size = file.getSize();
String type = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String fileUuid = uuid + "." + type;
File uploadFile = new File(destPath + "/" + fileUuid);
File parentFile = uploadFile.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
try {
String url;
String md5 = DigestUtils.md5DigestAsHex(file.getInputStream());
Files dbFiles = this.getFileByMD5(md5);
if (dbFiles != null) {
url = dbFiles.getUrl();
} else {
file.transferTo(uploadFile);
url = "http://localhost:8800/files/" + fileUuid;
}
Files saveFile = new Files();
saveFile.setFilesName(originalFilename);
saveFile.setType(type);
saveFile.setSize(size / 1024);
saveFile.setUrl(url);
saveFile.setMd5(md5);
save(saveFile);
return url;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
@Override
public void download(String filesUUID, HttpServletResponse response) {
try {
File uploadFile = new File(filesUploadPath + filesUUID);
FileInputStream fileInputStream = new FileInputStream(uploadFile);
InputStream inputStream = new BufferedInputStream(fileInputStream);
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filesUUID, "UTF-8"));
response.setContentType("application/octet-stream");
ServletOutputStream os = response.getOutputStream();
os.write(buffer);
fileInputStream.close();
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private Files getFileByMD5(String md5) {
QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("md5", md5);
List<Files> filesList = list(queryWrapper);
return filesList.size() == 0 ? null : filesList.get(0);
}
}
六、创建控制层和全局统一返回结果类
1、创建控制层FilesController。
@RestController
@RequestMapping("/files")
public class FilesController {
@Autowired
private FilesService filesService;
@PostMapping("upload")
public Result upload(@RequestParam MultipartFile file) {
String url = filesService.upload(file);
return Result.ok(url);
}
@GetMapping("/{filesUUID}")
public void download(@PathVariable String filesUUID, HttpServletResponse response) {
filesService.download(filesUUID, response);
}
2、创建返回类Result。
@Data
public class Result<T> {
private Integer code;
private String message;
private T data;
public Result() {
}
protected static <T> Result<T> build(T data) {
Result<T> result = new Result<T>();
if (data != null)
result.setData(data);
return result;
}
public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
Result<T> result = build(body);
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
return result;
}
public static <T> Result<T> build(Integer code, String message) {
Result<T> result = build(null);
result.setCode(code);
result.setMessage(message);
return result;
}
public static <T> Result<T> ok() {
return Result.ok(null);
}
public static <T> Result<T> ok(T data) {
Result<T> result = build(data);
return build(data, ResultCodeEnum.SUCCESS);
}
public static <T> Result<T> fail() {
return Result.fail(null);
}
public static <T> Result<T> fail(T data) {
Result<T> result = build(data);
return build(data, ResultCodeEnum.FAIL);
}
public Result<T> message(String msg) {
this.setMessage(msg);
return this;
}
public Result<T> code(Integer code) {
this.setCode(code);
return this;
}
public boolean isOk() {
if (this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
return true;
}
return false;
}
}
七、使用Postman测试
1、测试上传文件。
- 上传成功并返回url。
2. 查看数据库。
2、测试下载文件。
- 直接将返回的url复制到搜索引擎。
- 文件下载成功。
1、上传
-
使用el-upload标签。 <el-upload action="http://localhost:8800/files/upload"
:show-file-list="false"
:on-success="handleUploadSuccess"
style="display: inline-block">
<el-button type="primary" icon="el-icon-upload" style="margin-right: 10px">上传</el-button>
</el-upload>
-
文件上传成功时的钩子handleUploadSuccess。 methods: {
handleUploadSuccess(res) {
if (res.code === 200) {
this.$message.success("上传成功")
} else {
this.$message.error("上传失败")
}
},
}
2、下载
- 写个按钮el-button。
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-download" @click="download(scope.row.url)">下载</el-button>
</template>
- 定义方法download。
methods: {
download(row) {
file.downloadFiles(row).then(res => {
console.log(res)
})
},
}
|