✨ Introducing new features. 文件上传入库文件hash值
(cherry picked from commit 37178bcadff8aa29b50e43fb1b24063457f893ec)
This commit is contained in:
1 parent
ba15cf45cc
commit
03b3ecac55
4 files changed
+243
-225
No files matched your search
@@ -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 '修改人',
|
||||
|
||||
@@ -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 '修改人',
|
||||
|
||||
+79
-73
@@ -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;
|
||||
|
||||
}
|
||||
+162
-152
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user