feat(system): 优化文件上传功能并添加前端上传组件
- 修改后端文件上传接口,返回上传文件的URL - 新增文件上传前的本地校验逻辑- 实现文件拖拽上传功能 - 添加两个新的前端上传组件:CuteFileUpload 和 CuteFileDragUpload - 更新后端 MinioRepository 类,支持生成预签名 URL
This commit is contained in:
@@ -72,6 +72,8 @@ https://github.com/odboy-tianjun/cutejava
|
|||||||
|
|
||||||
- CuteDeptTree 部门树
|
- CuteDeptTree 部门树
|
||||||
- CuteUserSelect 用户多选框
|
- CuteUserSelect 用户多选框
|
||||||
|
- CuteFileUpload 上传文件到OSS, 必须结合Minio使用(上传完成后必须销毁组件)
|
||||||
|
- CuteFileDragUpload 支持拖拽上传文件到OSS, 必须结合Minio使用(上传完成后必须销毁组件)
|
||||||
|
|
||||||
#### 系统模块
|
#### 系统模块
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
drag
|
||||||
|
:limit="1"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:auto-upload="true"
|
||||||
|
:headers="headers"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
:action="ossUploadApi"
|
||||||
|
>
|
||||||
|
<i class="el-icon-upload" />
|
||||||
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
|
<div slot="tip" class="el-upload__tip">只能上传不超过100MB的文件</div>
|
||||||
|
</el-upload>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Message } from 'element-ui'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
export default {
|
||||||
|
name: 'CuteFileUpload',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
headers: { 'Authorization': getToken() }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
'baseApi',
|
||||||
|
'ossUploadApi'
|
||||||
|
])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
beforeUpload(file) {
|
||||||
|
let isLt2M = true
|
||||||
|
isLt2M = file.size / 1024 / 1024 < 100
|
||||||
|
if (!isLt2M) {
|
||||||
|
this.$message.error('上传文件大小不能超过 100MB')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isLt2M
|
||||||
|
},
|
||||||
|
// 监听上传失成功
|
||||||
|
handleSuccess(response, file, fileList) {
|
||||||
|
// Message.success('上传成功')
|
||||||
|
// this.$refs.upload.clearFiles()
|
||||||
|
console.error('response', response)
|
||||||
|
console.error('file', file)
|
||||||
|
console.error('fileList', fileList)
|
||||||
|
this.value.fileUrl = response
|
||||||
|
},
|
||||||
|
// 监听上传失败
|
||||||
|
handleError(e, file, fileList) {
|
||||||
|
const msg = JSON.parse(e.message)
|
||||||
|
Message.error(msg.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
:limit="1"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:auto-upload="true"
|
||||||
|
:headers="headers"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
:action="ossUploadApi"
|
||||||
|
>
|
||||||
|
<el-button size="small" type="primary">点击上传</el-button>
|
||||||
|
<div slot="tip" class="el-upload__tip">只能上传不超过100MB的文件</div>
|
||||||
|
</el-upload>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Message } from 'element-ui'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
export default {
|
||||||
|
name: 'CuteFileUpload',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
headers: { 'Authorization': getToken() }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
'baseApi',
|
||||||
|
'ossUploadApi'
|
||||||
|
])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
beforeUpload(file) {
|
||||||
|
let isLt2M = true
|
||||||
|
isLt2M = file.size / 1024 / 1024 < 100
|
||||||
|
if (!isLt2M) {
|
||||||
|
this.$message.error('上传文件大小不能超过 100MB')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isLt2M
|
||||||
|
},
|
||||||
|
// 监听上传失成功
|
||||||
|
handleSuccess(response, file, fileList) {
|
||||||
|
// Message.success('上传成功')
|
||||||
|
// this.$refs.upload.clearFiles()
|
||||||
|
console.error('response', response)
|
||||||
|
console.error('file', file)
|
||||||
|
console.error('fileList', fileList)
|
||||||
|
this.value.fileUrl = response
|
||||||
|
},
|
||||||
|
// 监听上传失败
|
||||||
|
handleError(e, file, fileList) {
|
||||||
|
const msg = JSON.parse(e.message)
|
||||||
|
Message.error(msg.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -40,9 +40,6 @@
|
|||||||
width="500px"
|
width="500px"
|
||||||
>
|
>
|
||||||
<el-form ref="form" :model="form" size="small" label-width="80px">
|
<el-form ref="form" :model="form" size="small" label-width="80px">
|
||||||
<el-form-item label="文件名">
|
|
||||||
<el-input v-model="form.name" style="width: 370px;" />
|
|
||||||
</el-form-item>
|
|
||||||
<!-- 上传文件 -->
|
<!-- 上传文件 -->
|
||||||
<el-form-item v-if="crud.status.add" label="上传">
|
<el-form-item v-if="crud.status.add" label="上传">
|
||||||
<el-upload
|
<el-upload
|
||||||
@@ -53,7 +50,7 @@
|
|||||||
:headers="headers"
|
:headers="headers"
|
||||||
:on-success="handleSuccess"
|
:on-success="handleSuccess"
|
||||||
:on-error="handleError"
|
:on-error="handleError"
|
||||||
:action="ossUploadApi + '?name=' + form.name"
|
:action="ossUploadApi"
|
||||||
>
|
>
|
||||||
<div class="my-upload"><i class="el-icon-upload" /> 添加文件</div>
|
<div class="my-upload"><i class="el-icon-upload" /> 添加文件</div>
|
||||||
<div slot="tip" class="el-upload__tip">可上传任意格式文件,且不超过100M</div>
|
<div slot="tip" class="el-upload__tip">可上传任意格式文件,且不超过100M</div>
|
||||||
@@ -106,7 +103,7 @@ import DateRangePicker from '@/components/DateRangePicker'
|
|||||||
import Clipboard from 'clipboard'
|
import Clipboard from 'clipboard'
|
||||||
import { Message } from 'element-ui'
|
import { Message } from 'element-ui'
|
||||||
|
|
||||||
const defaultForm = { id: null, name: '' }
|
const defaultForm = { id: null }
|
||||||
export default {
|
export default {
|
||||||
components: { pagination, crudOperation, rrOperation, DateRangePicker },
|
components: { pagination, crudOperation, rrOperation, DateRangePicker },
|
||||||
cruds() {
|
cruds() {
|
||||||
@@ -145,7 +142,6 @@ export default {
|
|||||||
this.loading = false
|
this.loading = false
|
||||||
this.$message.error('上传文件大小不能超过 100MB')
|
this.$message.error('上传文件大小不能超过 100MB')
|
||||||
}
|
}
|
||||||
this.form.name = file.name
|
|
||||||
return isLt2M
|
return isLt2M
|
||||||
},
|
},
|
||||||
handleSuccess(response, file, fileList) {
|
handleSuccess(response, file, fileList) {
|
||||||
|
|||||||
+3
-3
@@ -49,9 +49,9 @@ public class SystemOssStorageController {
|
|||||||
@ApiOperation("上传文件")
|
@ApiOperation("上传文件")
|
||||||
@PostMapping(value = "/uploadFile")
|
@PostMapping(value = "/uploadFile")
|
||||||
@PreAuthorize("@el.check('storage:add')")
|
@PreAuthorize("@el.check('storage:add')")
|
||||||
public ResponseEntity<Void> uploadFile(@RequestParam String name, @RequestParam("file") MultipartFile file) {
|
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
|
||||||
systemOssStorageService.uploadFile(name, file);
|
String fileUrl = systemOssStorageService.uploadFile(file);
|
||||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
return ResponseEntity.ok(fileUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("多选删除")
|
@ApiOperation("多选删除")
|
||||||
|
|||||||
+19
-26
@@ -11,7 +11,6 @@ import cn.odboy.framework.exception.BadRequestException;
|
|||||||
import cn.odboy.framework.properties.AppProperties;
|
import cn.odboy.framework.properties.AppProperties;
|
||||||
import cn.odboy.framework.properties.model.OSSConfigModel;
|
import cn.odboy.framework.properties.model.OSSConfigModel;
|
||||||
import cn.odboy.framework.properties.model.StorageOSSModel;
|
import cn.odboy.framework.properties.model.StorageOSSModel;
|
||||||
import cn.odboy.framework.server.core.FileUploadPathHelper;
|
|
||||||
import cn.odboy.system.dal.dataobject.SystemOssStorageTb;
|
import cn.odboy.system.dal.dataobject.SystemOssStorageTb;
|
||||||
import cn.odboy.util.CsDateUtil;
|
import cn.odboy.util.CsDateUtil;
|
||||||
import cn.odboy.util.FileUtil;
|
import cn.odboy.util.FileUtil;
|
||||||
@@ -38,7 +37,6 @@ import java.util.List;
|
|||||||
public class MinioRepository {
|
public class MinioRepository {
|
||||||
private final AppProperties properties;
|
private final AppProperties properties;
|
||||||
private final MinioClient minioClient;
|
private final MinioClient minioClient;
|
||||||
private final FileUploadPathHelper fileUploadPathHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查存储bucket是否存在
|
* 检查存储bucket是否存在
|
||||||
@@ -114,27 +112,19 @@ public class MinioRepository {
|
|||||||
/**
|
/**
|
||||||
* 文件上传
|
* 文件上传
|
||||||
*
|
*
|
||||||
* @param file 文件
|
* @param tempFile 文件
|
||||||
|
* @param originalFilename 源文件名
|
||||||
|
* @param fileSize 文件大小
|
||||||
|
* @param contentType 文件类型
|
||||||
|
* @param md5 文件md5
|
||||||
* @return String 上传后的文件名,上传失败返回 null
|
* @return String 上传后的文件名,上传失败返回 null
|
||||||
*/
|
*/
|
||||||
public SystemOssStorageTb upload(MultipartFile file) {
|
public SystemOssStorageTb upload(File tempFile, String originalFilename, long fileSize, String contentType, String md5) {
|
||||||
String originalFilename = file.getOriginalFilename();
|
|
||||||
if (StrUtil.isBlank(originalFilename)) {
|
|
||||||
throw new BadRequestException("文件名不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageOSSModel ossConfig = properties.getOss();
|
StorageOSSModel ossConfig = properties.getOss();
|
||||||
OSSConfigModel ossMinioConfig = ossConfig.getMinio();
|
OSSConfigModel ossMinioConfig = ossConfig.getMinio();
|
||||||
long fileSize = file.getSize();
|
String type = FileTypeUtil.getType(tempFile);
|
||||||
FileUtil.checkSize(ossConfig.getMaxSize(), fileSize);
|
String prefix = FileUtil.getPrefix(tempFile);
|
||||||
String contentType = file.getContentType();
|
String suffix = FileUtil.getSuffix(tempFile);
|
||||||
|
|
||||||
// 按天分组
|
|
||||||
String nowDateStr = CsDateUtil.getNowDateStr();
|
|
||||||
File tempFile = FileUtil.upload(file, fileUploadPathHelper.getPath() + nowDateStr + File.separator);
|
|
||||||
if (tempFile == null) {
|
|
||||||
throw new BadRequestException("上传失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
String fileCode = IdUtil.fastSimpleUUID();
|
String fileCode = IdUtil.fastSimpleUUID();
|
||||||
String fileName = fileCode + getFileExtension(originalFilename);
|
String fileName = fileCode + getFileExtension(originalFilename);
|
||||||
@@ -148,10 +138,10 @@ public class MinioRepository {
|
|||||||
systemOssStorageTb.setBucketName(StrUtil.trim(ossMinioConfig.getBucketName()));
|
systemOssStorageTb.setBucketName(StrUtil.trim(ossMinioConfig.getBucketName()));
|
||||||
systemOssStorageTb.setFileName(originalFilename);
|
systemOssStorageTb.setFileName(originalFilename);
|
||||||
systemOssStorageTb.setFileSize(fileSize);
|
systemOssStorageTb.setFileSize(fileSize);
|
||||||
systemOssStorageTb.setFileMime(FileTypeUtil.getType(tempFile));
|
systemOssStorageTb.setFileMime(type);
|
||||||
systemOssStorageTb.setFilePrefix(FileUtil.getPrefix(tempFile));
|
systemOssStorageTb.setFilePrefix(prefix);
|
||||||
systemOssStorageTb.setFileSuffix(FileUtil.getSuffix(tempFile));
|
systemOssStorageTb.setFileSuffix(suffix);
|
||||||
systemOssStorageTb.setFileMd5(FileUtil.getMd5(tempFile));
|
systemOssStorageTb.setFileMd5(md5);
|
||||||
systemOssStorageTb.setFileUrl(fileUrl);
|
systemOssStorageTb.setFileUrl(fileUrl);
|
||||||
systemOssStorageTb.setFileCode(fileCode);
|
systemOssStorageTb.setFileCode(fileCode);
|
||||||
systemOssStorageTb.setObjectName(objectName);
|
systemOssStorageTb.setObjectName(objectName);
|
||||||
@@ -276,9 +266,12 @@ public class MinioRepository {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
GetPresignedObjectUrlArgs presignedUrlArgs = GetPresignedObjectUrlArgs.builder().bucket(properties.getOss().getMinio().getBucketName()).object(fullFileName).method(Method.GET)
|
GetPresignedObjectUrlArgs presignedUrlArgs = GetPresignedObjectUrlArgs.builder()
|
||||||
// 设置 URL 过期时间为 1 小时
|
.bucket(properties.getOss().getMinio().getBucketName())
|
||||||
.expiry(3600).build();
|
.object(fullFileName)
|
||||||
|
.method(Method.GET)
|
||||||
|
// 设置 URL 过期时间为 7 天, 最大 7 天, 别挣扎了
|
||||||
|
.expiry(3600 * 24 * 7).build();
|
||||||
String url = minioClient.getPresignedObjectUrl(presignedUrlArgs);
|
String url = minioClient.getPresignedObjectUrl(presignedUrlArgs);
|
||||||
log.info("生成预签名 URL 成功,fileName: {}, url: {}", fullFileName, url);
|
log.info("生成预签名 URL 成功,fileName: {}, url: {}", fullFileName, url);
|
||||||
return url;
|
return url;
|
||||||
|
|||||||
+3
-1
@@ -27,7 +27,9 @@ public interface SystemOssStorageService extends IService<SystemOssStorageTb> {
|
|||||||
|
|
||||||
void exportOssStorageExcel(List<SystemOssStorageVo> list, HttpServletResponse response) throws IOException;
|
void exportOssStorageExcel(List<SystemOssStorageVo> list, HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
void uploadFile(String name, MultipartFile file);
|
String uploadFile(MultipartFile file);
|
||||||
|
|
||||||
void removeFileByIds(Long[] ids);
|
void removeFileByIds(Long[] ids);
|
||||||
|
|
||||||
|
SystemOssStorageTb getByMd5(String md5);
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-2
@@ -1,14 +1,19 @@
|
|||||||
package cn.odboy.system.service.impl;
|
package cn.odboy.system.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.odboy.base.CsResultVo;
|
import cn.odboy.base.CsResultVo;
|
||||||
import cn.odboy.framework.exception.BadRequestException;
|
import cn.odboy.framework.exception.BadRequestException;
|
||||||
|
import cn.odboy.framework.properties.AppProperties;
|
||||||
|
import cn.odboy.framework.properties.model.StorageOSSModel;
|
||||||
|
import cn.odboy.framework.server.core.FileUploadPathHelper;
|
||||||
import cn.odboy.system.dal.dataobject.SystemOssStorageTb;
|
import cn.odboy.system.dal.dataobject.SystemOssStorageTb;
|
||||||
import cn.odboy.system.dal.model.SystemOssStorageVo;
|
import cn.odboy.system.dal.model.SystemOssStorageVo;
|
||||||
import cn.odboy.system.dal.model.SystemQueryStorageArgs;
|
import cn.odboy.system.dal.model.SystemQueryStorageArgs;
|
||||||
import cn.odboy.system.dal.mysql.SystemOssStorageMapper;
|
import cn.odboy.system.dal.mysql.SystemOssStorageMapper;
|
||||||
import cn.odboy.system.framework.storage.minio.MinioRepository;
|
import cn.odboy.system.framework.storage.minio.MinioRepository;
|
||||||
import cn.odboy.system.service.SystemOssStorageService;
|
import cn.odboy.system.service.SystemOssStorageService;
|
||||||
|
import cn.odboy.util.CsDateUtil;
|
||||||
import cn.odboy.util.CsPageUtil;
|
import cn.odboy.util.CsPageUtil;
|
||||||
import cn.odboy.util.FileUtil;
|
import cn.odboy.util.FileUtil;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
@@ -20,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -38,6 +44,8 @@ import java.util.Map;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SystemOssStorageServiceImpl extends ServiceImpl<SystemOssStorageMapper, SystemOssStorageTb> implements SystemOssStorageService {
|
public class SystemOssStorageServiceImpl extends ServiceImpl<SystemOssStorageMapper, SystemOssStorageTb> implements SystemOssStorageService {
|
||||||
private final MinioRepository minioRepository;
|
private final MinioRepository minioRepository;
|
||||||
|
private final AppProperties properties;
|
||||||
|
private final FileUploadPathHelper fileUploadPathHelper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CsResultVo<List<SystemOssStorageVo>> queryOssStorage(SystemQueryStorageArgs criteria, Page<SystemOssStorageTb> page) {
|
public CsResultVo<List<SystemOssStorageVo>> queryOssStorage(SystemQueryStorageArgs criteria, Page<SystemOssStorageTb> page) {
|
||||||
@@ -77,12 +85,36 @@ public class SystemOssStorageServiceImpl extends ServiceImpl<SystemOssStorageMap
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void uploadFile(String name, MultipartFile file) {
|
public String uploadFile(MultipartFile file) {
|
||||||
SystemOssStorageTb storageTb = minioRepository.upload(file);
|
String originalFilename = file.getOriginalFilename();
|
||||||
|
if (StrUtil.isBlank(originalFilename)) {
|
||||||
|
throw new BadRequestException("文件名不能为空");
|
||||||
|
}
|
||||||
|
StorageOSSModel ossConfig = properties.getOss();
|
||||||
|
long fileSize = file.getSize();
|
||||||
|
String contentType = file.getContentType();
|
||||||
|
FileUtil.checkSize(ossConfig.getMaxSize(), fileSize);
|
||||||
|
// 按天分组
|
||||||
|
String nowDateStr = CsDateUtil.getNowDateStr();
|
||||||
|
// 上传到本地临时目录
|
||||||
|
File tempFile = FileUtil.upload(file, fileUploadPathHelper.getPath() + nowDateStr + File.separator);
|
||||||
|
if (tempFile == null) {
|
||||||
|
throw new BadRequestException("上传失败");
|
||||||
|
}
|
||||||
|
// 校验文件md5, 看是否已存在云端(不确定, 可能云端已经删除, 但是正常来说云端是不允许私自删除的, 所以这里忽略云端不存在的情况)
|
||||||
|
String md5 = FileUtil.getMd5(tempFile);
|
||||||
|
SystemOssStorageTb systemOssStorageTb = getByMd5(md5);
|
||||||
|
if (systemOssStorageTb != null) {
|
||||||
|
// 重新生成7天链接
|
||||||
|
return minioRepository.generatePreviewUrl(systemOssStorageTb.getObjectName());
|
||||||
|
}
|
||||||
|
// 上传到OSS
|
||||||
|
SystemOssStorageTb storageTb = minioRepository.upload(tempFile, originalFilename, fileSize, contentType, md5);
|
||||||
if (storageTb == null) {
|
if (storageTb == null) {
|
||||||
throw new BadRequestException("文件上传失败");
|
throw new BadRequestException("文件上传失败");
|
||||||
}
|
}
|
||||||
save(storageTb);
|
save(storageTb);
|
||||||
|
return minioRepository.generatePreviewUrl(storageTb.getObjectName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,4 +130,9 @@ public class SystemOssStorageServiceImpl extends ServiceImpl<SystemOssStorageMap
|
|||||||
removeById(storage);
|
removeById(storage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemOssStorageTb getByMd5(String md5) {
|
||||||
|
return lambdaQuery().eq(SystemOssStorageTb::getFileMd5, md5).one();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user