✨ Introducing new features. 文件上传入库文件hash值

(cherry picked from commit 37178bcadff8aa29b50e43fb1b24063457f893ec)
This commit is contained in:
冷冷 committed 2024-08-16 15:17:30 +08:00
1 parent ba15cf45cc
commit 03b3ecac55
4 files changed
+243 -225

No files matched your search

+1
View File
@@ -312,6 +312,7 @@ CREATE TABLE `sys_file` (
`dir` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件夹名称',
`original` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '原始文件名',
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件类型',
`hash` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件hash',
`file_size` bigint(20) DEFAULT NULL COMMENT '文件大小',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '修改人',
+1
View File
@@ -309,6 +309,7 @@ CREATE TABLE `sys_file` (
`dir` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件夹名称',
`original` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '原始文件名',
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件类型',
`hash` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件hash',
`file_size` bigint(20) DEFAULT NULL COMMENT '文件大小',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '创建人',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ' ' COMMENT '修改人',
@@ -38,91 +38,97 @@ import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = true)
public class SysFile extends Model<SysFile> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "文件编号")
private Long id;
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "文件编号")
private Long id;
/**
* 文件名
*/
@Schema(description = "文件名")
private String fileName;
/**
* 文件名
*/
@Schema(description = "文件名")
private String fileName;
/**
* 原文件名
*/
@Schema(description = "原始文件名")
private String original;
/**
* 原文件名
*/
@Schema(description = "原始文件名")
private String original;
/**
* 容器名称
*/
@Schema(description = "存储桶名称")
private String bucketName;
/**
* 容器名称
*/
@Schema(description = "存储桶名称")
private String bucketName;
/***
* 文件夹
*/
@Schema(description = "文件夹")
private String dir;
/***
* 文件夹
*/
@Schema(description = "文件夹")
private String dir;
/**
* 文件类型
*/
@Schema(description = "文件类型")
private String type;
/**
* 文件类型
*/
@Schema(description = "文件类型")
private String type;
/**
* 文件组
*/
@Schema(description = "文件组")
private Long groupId;
/**
* 文件组
*/
@Schema(description = "文件组")
private Long groupId;
/**
* 文件大小
*/
@Schema(description = "文件大小")
private Long fileSize;
/**
* 文件大小
*/
@Schema(description = "文件大小")
private Long fileSize;
/**
* 上传人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建者")
private String createBy;
/**
* 文件hash
*/
@Schema(description = "文件hash")
private String hash;
/**
* 上传时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 上传人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建者")
private String createBy;
/**
* 更新人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "更新者")
private String updateBy;
/**
* 上传时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE)
@Schema(description = "更新时间")
private LocalDateTime updateTime;
/**
* 更新人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "更新者")
private String updateBy;
/**
* 删除标识:1-删除,0-正常
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记,1:已删除,0:正常")
private String delFlag;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE)
@Schema(description = "更新时间")
private LocalDateTime updateTime;
/**
* 删除标识:1-删除,0-正常
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记,1:已删除,0:正常")
private String delFlag;
}
@@ -24,6 +24,7 @@ import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.amazonaws.services.s3.model.S3Object;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -61,173 +62,182 @@ import java.util.*;
@AllArgsConstructor
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements SysFileService {
private final FileTemplate fileTemplate;
private final FileTemplate fileTemplate;
private final SysFileGroupMapper fileGroupMapper;
private final SysFileGroupMapper fileGroupMapper;
private final FileProperties properties;
private final FileProperties properties;
/**
* 上传文件
* @param file 文件流
* @param dir 文件夹
* @param groupId 分组ID
* @param type 类型
* @return
*/
@Override
public R uploadFile(MultipartFile file, String dir, Long groupId, String type) {
String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
Map<String, String> resultMap = new HashMap<>(4);
resultMap.put("bucketName", properties.getBucketName());
resultMap.put("fileName", fileName);
/**
* 上传文件
*
* @param file 文件流
* @param dir 文件夹
* @param groupId 分组ID
* @param type 类型
* @return
*/
@Override
public R uploadFile(MultipartFile file, String dir, Long groupId, String type) {
String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
Map<String, String> resultMap = new HashMap<>(4);
resultMap.put("bucketName", properties.getBucketName());
resultMap.put("fileName", fileName);
resultMap.put("url", String.format("/admin/sys-file/oss/file?fileName=%s", fileName));
resultMap.put("url", String.format("/admin/sys-file/oss/file?fileName=%s", fileName));
try (InputStream inputStream = file.getInputStream()) {
fileTemplate.putObject(properties.getBucketName(), dir, fileName, inputStream, file.getContentType());
// 文件管理数据记录,收集管理追踪文件
fileLog(file, dir, fileName, groupId, type);
}
catch (Exception e) {
log.error("上传失败", e);
return R.failed(e.getLocalizedMessage());
}
return R.ok(resultMap);
}
try (InputStream inputStream = file.getInputStream()) {
fileTemplate.putObject(properties.getBucketName(), dir, fileName, inputStream, file.getContentType());
// 文件管理数据记录,收集管理追踪文件
fileLog(file, dir, fileName, groupId, type);
} catch (Exception e) {
log.error("上传失败", e);
return R.failed(e.getLocalizedMessage());
}
return R.ok(resultMap);
}
/**
* 读取文件
* @param bucket
* @param fileName
* @param response
*/
@Override
public void getFile(String fileName, HttpServletResponse response) {
TenantContextHolder.setTenantSkip();
SysFile sysFile = baseMapper.selectOne(Wrappers.<SysFile>lambdaQuery().eq(SysFile::getFileName, fileName));
try (S3Object s3Object = fileTemplate.getObject(sysFile.getBucketName(), sysFile.getDir(), fileName)) {
response.setContentType("application/octet-stream; charset=UTF-8");
IoUtil.copy(s3Object.getObjectContent(), response.getOutputStream());
}
catch (Exception e) {
log.error("文件读取异常: {}", e.getLocalizedMessage());
}
}
/**
* 读取文件
*
* @param bucket
* @param fileName
* @param response
*/
@Override
public void getFile(String fileName, HttpServletResponse response) {
TenantContextHolder.setTenantSkip();
SysFile sysFile = baseMapper.selectOne(Wrappers.<SysFile>lambdaQuery().eq(SysFile::getFileName, fileName));
try (S3Object s3Object = fileTemplate.getObject(sysFile.getBucketName(), sysFile.getDir(), fileName)) {
response.setContentType("application/octet-stream; charset=UTF-8");
// 文件唯一hash
response.addHeader("Hash", sysFile.getHash());
IoUtil.copy(s3Object.getObjectContent(), response.getOutputStream());
} catch (Exception e) {
log.error("文件读取异常: {}", e.getLocalizedMessage());
}
}
/**
* 删除文件
* @param id
* @return
*/
@Override
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public Boolean deleteFile(Long id) {
SysFile file = this.getById(id);
if (Objects.isNull(file)) {
return Boolean.FALSE;
}
fileTemplate.removeObject(properties.getBucketName(), file.getFileName());
return this.removeById(id);
}
/**
* 删除文件
*
* @param id
* @return
*/
@Override
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public Boolean deleteFile(Long id) {
SysFile file = this.getById(id);
if (Objects.isNull(file)) {
return Boolean.FALSE;
}
fileTemplate.removeObject(properties.getBucketName(), file.getFileName());
return this.removeById(id);
}
/**
* 查询文件组列表
* @param fileGroup SysFileGroup对象,用于筛选条件
* @return 包含文件组树形结构列表的List对象
*/
@Override
public List<Tree<Long>> listFileGroup(SysFileGroup fileGroup) {
// 从数据库查询文件组列表
List<TreeNode<Long>> treeNodeList = fileGroupMapper.selectList(Wrappers.query(fileGroup))
.stream()
.map(group -> {
TreeNode<Long> treeNode = new TreeNode<>();
treeNode.setName(group.getName());
treeNode.setId(group.getId());
treeNode.setParentId(group.getPid());
return treeNode;
})
.toList();
/**
* 查询文件组列表
*
* @param fileGroup SysFileGroup对象,用于筛选条件
* @return 包含文件组树形结构列表的List对象
*/
@Override
public List<Tree<Long>> listFileGroup(SysFileGroup fileGroup) {
// 从数据库查询文件组列表
List<TreeNode<Long>> treeNodeList = fileGroupMapper.selectList(Wrappers.query(fileGroup))
.stream()
.map(group -> {
TreeNode<Long> treeNode = new TreeNode<>();
treeNode.setName(group.getName());
treeNode.setId(group.getId());
treeNode.setParentId(group.getPid());
return treeNode;
})
.toList();
// 构建树形结构
List<Tree<Long>> treeList = TreeUtil.build(treeNodeList, CommonConstants.MENU_TREE_ROOT_ID);
return CollUtil.isEmpty(treeList) ? new ArrayList<>() : treeList;
}
// 构建树形结构
List<Tree<Long>> treeList = TreeUtil.build(treeNodeList, CommonConstants.MENU_TREE_ROOT_ID);
return CollUtil.isEmpty(treeList) ? new ArrayList<>() : treeList;
}
/**
* 添加或更新文件组
* @param fileGroup SysFileGroup对象,要添加或更新的文件组信息
* @return 添加或更新成功返回true,否则返回false
*/
@Override
public Boolean saveOrUpdateGroup(SysFileGroup fileGroup) {
if (Objects.isNull(fileGroup.getId())) {
// 插入文件组
fileGroupMapper.insert(fileGroup);
}
else {
// 更新文件组
fileGroupMapper.updateById(fileGroup);
}
return Boolean.TRUE;
}
/**
* 添加或更新文件组
*
* @param fileGroup SysFileGroup对象,要添加或更新的文件组信息
* @return 添加或更新成功返回true,否则返回false
*/
@Override
public Boolean saveOrUpdateGroup(SysFileGroup fileGroup) {
if (Objects.isNull(fileGroup.getId())) {
// 插入文件组
fileGroupMapper.insert(fileGroup);
} else {
// 更新文件组
fileGroupMapper.updateById(fileGroup);
}
return Boolean.TRUE;
}
/**
* 删除文件组
* @param id 待删除文件组的ID
* @return 删除成功返回true,否则返回false
*/
@Override
public Boolean deleteGroup(Long id) {
// 根据ID删除文件组
fileGroupMapper.deleteById(id);
return Boolean.TRUE;
}
/**
* 删除文件组
*
* @param id 待删除文件组的ID
* @return 删除成功返回true,否则返回false
*/
@Override
public Boolean deleteGroup(Long id) {
// 根据ID删除文件组
fileGroupMapper.deleteById(id);
return Boolean.TRUE;
}
/**
* 移动文件组
* @param fileGroupDTO SysFileGroupDTO对象,要移动的文件组信息
* @return 移动成功返回true,否则返回false
*/
@Override
public Boolean moveFileGroup(SysFileGroupDTO fileGroupDTO) {
// 创建SysFile对象并设置groupId属性
SysFile file = new SysFile();
file.setGroupId(fileGroupDTO.getGroupId());
/**
* 移动文件组
*
* @param fileGroupDTO SysFileGroupDTO对象,要移动的文件组信息
* @return 移动成功返回true,否则返回false
*/
@Override
public Boolean moveFileGroup(SysFileGroupDTO fileGroupDTO) {
// 创建SysFile对象并设置groupId属性
SysFile file = new SysFile();
file.setGroupId(fileGroupDTO.getGroupId());
// 根据IDS更新对应的SysFile记录
baseMapper.update(file, Wrappers.<SysFile>lambdaQuery().in(SysFile::getId, fileGroupDTO.getIds()));
return Boolean.TRUE;
}
// 根据IDS更新对应的SysFile记录
baseMapper.update(file, Wrappers.<SysFile>lambdaQuery().in(SysFile::getId, fileGroupDTO.getIds()));
return Boolean.TRUE;
}
/**
* 文件管理数据记录,收集管理追踪文件
* @param file 上传的文件格式
* @param dir 文件夹
* @param fileName 文件名
* @param groupId 文件组ID
* @param type 文件类型
*/
private void fileLog(MultipartFile file, String dir, String fileName, Long groupId, String type) {
// 创建SysFile对象并设置相关属性
SysFile sysFile = new SysFile();
sysFile.setFileName(fileName);
/**
* 文件管理数据记录,收集管理追踪文件
*
* @param file 上传的文件格式
* @param dir 文件夹
* @param fileName 文件名
* @param groupId 文件组ID
* @param type 文件类型
*/
@SneakyThrows
private void fileLog(MultipartFile file, String dir, String fileName, Long groupId, String type) {
// 创建SysFile对象并设置相关属性
SysFile sysFile = new SysFile();
sysFile.setFileName(fileName);
// 对原始文件名进行编码转换
String originalFilename = new String(
Objects.requireNonNull(file.getOriginalFilename()).getBytes(StandardCharsets.ISO_8859_1),
StandardCharsets.UTF_8);
sysFile.setDir(dir);
sysFile.setOriginal(originalFilename);
sysFile.setFileSize(file.getSize());
sysFile.setBucketName(properties.getBucketName());
sysFile.setType(type);
sysFile.setGroupId(groupId);
// 对原始文件名进行编码转换
String originalFilename = new String(
Objects.requireNonNull(file.getOriginalFilename()).getBytes(StandardCharsets.ISO_8859_1),
StandardCharsets.UTF_8);
sysFile.setDir(dir);
sysFile.setOriginal(originalFilename);
sysFile.setFileSize(file.getSize());
sysFile.setBucketName(properties.getBucketName());
sysFile.setType(type);
sysFile.setGroupId(groupId);
// 调用save方法保存SysFile对象
this.save(sysFile);
}
sysFile.setHash(SecureUtil.md5(file.getInputStream()));
// 调用save方法保存SysFile对象
this.save(sysFile);
}
}