代码提交

This commit is contained in:
lilin 2025-05-27 19:38:40 +08:00
parent aed54f863f
commit 5a41e32f7a
5 changed files with 196 additions and 172 deletions

View File

@ -273,9 +273,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_parentId" + id + "_page_" + currentPage + ""; String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_parentId" + id + "_page_" + currentPage + "";
redisTemplate.opsForValue().set(redisKey, tsFilesPage, 2, TimeUnit.HOURS); redisTemplate.opsForValue().set(redisKey, tsFilesPage, 2, TimeUnit.HOURS);
} }
} else {
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage;
redisTemplate.delete(redisKey);
} }
return tsFilesPage; return tsFilesPage;

View File

@ -80,18 +80,12 @@ public class FilesController {
@ApiOperation("新增专项文档管理文档内容") @ApiOperation("新增专项文档管理文档内容")
@ResponseBody @ResponseBody
@PreAuthorize("@el.check('add:files')") @PreAuthorize("@el.check('add:files')")
public ResponseResult addFiles(@RequestBody Files files,String sourcePath,String targetPath) throws Exception { public ResponseResult addFiles(@RequestBody Files files) throws Exception {
//对象不能为空 //对象不能为空
if (ObjUtil.isEmpty(files)) { if (ObjUtil.isEmpty(files)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
if (StrUtil.isEmpty(sourcePath)) { return filesService.addFiles(files);
return ResponseResult.error("源路径参数为空");
}
if (StrUtil.isEmpty(targetPath)) {
return ResponseResult.error("目标路径参数为空");
}
return filesService.addFiles(files,sourcePath,targetPath);
} }

View File

@ -111,4 +111,16 @@ public class Files implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String type; private String type;
/**
* 源路径TODO 增加用于前端展示
*/
@TableField(exist = false)
private String sourcePath;
/**
* 目标路径TODO 增加用于前端展示
*/
@TableField(exist = false)
private String targetPath;
} }

View File

@ -43,7 +43,7 @@ public interface IFilesService extends IService<Files> {
* targetPath 目标路径 * targetPath 目标路径
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败 * 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/ ***********************************/
ResponseResult addFiles(Files files,String sourcePath,String targetPath) throws Exception; ResponseResult addFiles(Files files) throws Exception;
/********************************** /**********************************
* 用途说明: 修改专项文档管理-文档内容 * 用途说明: 修改专项文档管理-文档内容

View File

@ -3,6 +3,7 @@ package com.yfd.platform.modules.specialDocument.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@ -35,6 +36,7 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -47,6 +49,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Path; import java.nio.file.Path;
@ -245,6 +248,7 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
return null; // 或返回空分页对象 new Page<>(0) return null; // 或返回空分页对象 new Page<>(0)
} }
private boolean isValidPage(IPage<Files> page) { private boolean isValidPage(IPage<Files> page) {
return page.getRecords() != null return page.getRecords() != null
&& !page.getRecords().isEmpty() && !page.getRecords().isEmpty()
@ -261,31 +265,9 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败 * 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/ ***********************************/
@Override @Override
public ResponseResult addFiles(Files files,String sourcePath,String targetPath) throws Exception { public ResponseResult addFiles(Files files) throws Exception {
Boolean value = false; Boolean value = false;
//新增之前从处理一下源路径的数据
// 查询本地文件路径根目录 E:\yun
QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "filePath");
queryWrapper.eq("type", "sdlocal");
StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
//源路径 临时路径
String sourceFilePath = storageSourceConfig.getValue()+sourcePath;
//目标路径
String targetFilePath = storageSourceConfig.getValue()+targetPath;
this.documentUploadById(files,sourceFilePath,targetFilePath,storageSourceConfig.getValue());
List<String> names = Arrays.asList(files.getFileName().split(","));
List<String> sizes = Arrays.asList(files.getFileSize().split(","));
//todo 新增成功以后 删除redis //todo 新增成功以后 删除redis
for (int page = 1; page <= 5; page++) { for (int page = 1; page <= 5; page++) {
String redisKey = "sdfiles_" + files.getProjectId() + "_" + files.getNodeId() + "_page_" + page; String redisKey = "sdfiles_" + files.getProjectId() + "_" + files.getNodeId() + "_page_" + page;
@ -293,73 +275,53 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
} }
LOGGER.info("已清理缓存project={}, node={}, pages=1-5", files.getProjectId(), files.getNodeId()); LOGGER.info("已清理缓存project={}, node={}, pages=1-5", files.getProjectId(), files.getNodeId());
// 差不多的流程 就是提出来 然后判断 如果两个 中有一个是true
//获取当前登录用户 上传人是当前登录人 //获取当前登录用户 上传人是当前登录人
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal(); LoginUser loginuser = null;
if (authentication != null) {
loginuser = (LoginUser) authentication.getPrincipal();
// 数据校验
if (names.size() != sizes.size()) {
return ResponseResult.error("文件名称和文件大小的列表长度不一致!");
} }
List<Files> filesToSave = new ArrayList<>();
// 设置当前时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
files.setUploadTime(currentTime);
//新增之前从处理一下源路径的数据 ,String sourcePath,String targetPath
// 查询本地文件路径根目录 E:\yun
QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "filePath");
queryWrapper.eq("type", "sdlocal");
StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
//源路径 临时路径
String sourceFilePath = files.getSourcePath();
//目标路径
String targetFilePath = files.getTargetPath();
for (int i = 0; i < names.size(); i++) { List<Files> filesToSave = this.documentUploadById(files, sourceFilePath, targetFilePath, storageSourceConfig.getValue());
String name = names.get(i).trim();
String sizeStr = sizes.get(i).trim();
// 校验文件名是否包含非法字符
if (containsInvalidCharacters(name)) {
return ResponseResult.error("文件名包含非法字符!");
}
//校验是否真正上传
String pathAndName = files.getFilePath() + "/" + name;
//准备获取文件的信息
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("sdlocal");
FileItemResult fileItemResult = fileService.getFileItem(pathAndName);
if (fileItemResult == null || fileItemResult.getName() == null) {
return ResponseResult.error(name + "文件没有上传到空间,请重新选择上传!");
}
// 校验文件大小是否可以转换成数值
try {
Files files1 = new Files();
files1.setProjectId(files.getProjectId());
files1.setNodeId(files.getNodeId());
files1.setFilePath(files.getFilePath());
files1.setKeywords(files.getKeywords());
files1.setDescription(files.getDescription());
files1.setUploadTime(files.getUploadTime());
files1.setUploader(loginuser.getUsername());
files1.setFileName(name);
files1.setFileSize(sizeStr);
filesToSave.add(files1);
} catch (NumberFormatException e) {
return ResponseResult.error("文件大小必须是有效的数字!");
}
}
if (filesToSave.size() > 0) { if (filesToSave.size() > 0) {
//循环新增 //循环新增
for (Files filess : filesToSave) { for (Files filess : filesToSave) {
if (loginuser != null) {
filess.setUploader(loginuser.getUsername());
}
//校验是否真正上传
String pathAndName = filess.getFilePath() + filess.getFileName();
//准备获取文件的信息
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("sdlocal");
FileItemResult fileItemResult = fileService.getFileItem(pathAndName);
if (fileItemResult == null || fileItemResult.getName() == null) {
return ResponseResult.error(filess.getFileName() + "文件没有上传到空间,请重新选择上传!");
}
int valueAdded = filesMapper.insert(filess); int valueAdded = filesMapper.insert(filess);
if (valueAdded == 1) { if (valueAdded == 1) {
value = true; value = true;
} else { } else {
value = false; value = false;
} }
} }
} }
File target = new File(storageSourceConfig.getValue() + String.valueOf(sourceFilePath));
//删除临时文件
deleteDirectory(target);
if (value) { if (value) {
return ResponseResult.success("新增文件成功!"); return ResponseResult.success("新增文件成功!");
} else { } else {
@ -367,89 +329,145 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
} }
} }
public String documentUploadById(Files files, String sourceFilePath, String targetFilePath, String value) throws Exception { public static void deleteDirectory(File directory) throws Exception {
return null; if (!directory.exists()) {
return; // 路径不存在直接返回
}
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteDirectory(file); // 递归删除子目录
} else {
if (!file.delete()) { // 删除文件
throw new Exception("无法删除文件: " + file.getAbsolutePath());
}
}
}
}
if (!directory.delete()) { // 删除空目录
throw new Exception("无法删除目录: " + directory.getAbsolutePath());
}
}
public List<Files> documentUploadById(Files files, String sourceFilePath, String targetFilePath, String value) throws Exception {
List<Files> filesList = new ArrayList<>();
// 设置当前时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
FileListRequest sourcefileListRequest = buildFileRequest(sourceFilePath);
FileListRequest targetfileListRequest = buildFileRequest(targetFilePath);
//获取源文件列表 包含文件和文件夹
List<FileItemResult> sourceFileItemList = obtainFileItemResultData(sourcefileListRequest);
//获取目标文件列表 包含文件和文件夹
List<FileItemResult> targetFileItemList = obtainFileItemResultData(targetfileListRequest);
for (FileItemResult fileItemResult : sourceFileItemList) {
String a1 = fileItemResult.getType() + fileItemResult.getName();
FileItemResult targetFileItem = targetFileItemList.stream()
.filter(t -> (t.getType() + t.getName()).equals(a1))
.findFirst() // 获取第一个匹配项返回 Optional
.orElse(null);
// 检查对象存在
if (targetFileItem != null) {
// 循环处理文件 对比文件的MD5值
if (fileItemResult.getType() == FileTypeEnum.FILE) {
//源路径
String sourcePath = value + sourceFilePath + "/" + fileItemResult.getName();
//目标路径
String targetPath = value + targetFilePath + "/" + fileItemResult.getName();
//根据路径获取MD5值比较 如果相同则不进行操作 如果不同则重命名目标路径下的文件名称以及表结构 把现在源路径下的文件拷贝到目标路径下 新增数据库文件记录
// 计算源文件MD5
File sourceLocalFile = new File(sourcePath);
String sourceLocalMD5 = calculateMD5Data(new FileInputStream(sourceLocalFile));
// 计算源文件MD5
File targetLocalFile = new File(targetPath);
String targetLocalMD5 = calculateMD5Data(new FileInputStream(targetLocalFile));
// 如果MD5值不相同则进行操作 //如果一致 则直接复制源文件到目标文件
if (StringUtils.isNoneEmpty(sourceLocalMD5, targetLocalMD5) && !sourceLocalMD5.equals(targetLocalMD5)) {
//更改目标路径下的文件名称
String newTargetPath = renameFile(sourcePath);
//将源目录文件 复制到 目标目录文件
copyToDirectoryFile(newTargetPath, value + targetFilePath + "/");
String normalizedPath = newTargetPath
.replaceAll("[/\\\\]+", "/") // "\" 或混合分隔符统一为 "/"
.replaceAll("/+$", "");
String fileName = normalizedPath.substring(normalizedPath.lastIndexOf("/") + 1);
Files files1 = new Files();
files1.setProjectId(files.getProjectId());
files1.setNodeId(files.getNodeId());
files1.setFileName(fileName);
//todo
files1.setFilePath(targetFilePath);
long fileSizeInBytes = fileItemResult.getSize();
// 转换为 MB 并保留两位小数
double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0);
String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数
files1.setFileSize(fileSizeFormatted);
files1.setUploadTime(currentTime);
filesList.add(files1);
} else {
//将源目录文件 复制到 目标目录文件 todo这个地方是覆盖
copyWithOverride(sourcePath, targetPath);
}
}
} else {
//如果为空对象不存在 则直接拷贝
String sourcePath = value + sourceFilePath;
//目标路径
String targetPath = value + targetFilePath;
//将源目录文件 复制到 目标目录文件
copyFolderWithOverride(sourcePath, targetPath);
//这个时候要新增
Files files1 = new Files();
files1.setProjectId(files.getProjectId());
files1.setNodeId(files.getNodeId());
files1.setFileName(fileItemResult.getName());
//todo
files1.setFilePath(targetFilePath);
long fileSizeInBytes = fileItemResult.getSize();
// 转换为 MB 并保留两位小数
double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0);
String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数
files1.setFileSize(fileSizeFormatted);
files1.setUploadTime(currentTime);
filesList.add(files1);
}
}
return filesList;
}
/**
* 确保路径格式为以 "/" 开头和结尾例如 "/data/test/"
* 若路径为空或非法返回根路径 "/"
*/
private String ensurePathFormat(String path) {
if (StringUtils.isBlank(path)) {
return "/";
}
// 统一替换反斜杠为斜杠兼容 Windows 路径
String normalized = path.replaceAll("\\\\", "/");
// 去掉多余的斜杠
normalized = normalized.replaceAll("/{2,}", "/");
// 确保以 "/" 开头
if (!normalized.startsWith("/")) {
normalized = "/" + normalized;
}
// 确保以 "/" 结尾
if (!normalized.endsWith("/")) {
normalized += "/";
}
return normalized;
} }
// List<Files> filesList = new ArrayList<>();
//
//
// //源目录
// File sourceDir = new File(sourceFilePath);
// //目标目录
// File targetDir = new File(targetFilePath);
//
// if (!targetDir.exists()) {
// FileUtils.copyDirectory(sourceDir, targetDir);
// LOGGER.info("目标文件没有,全部更新过去");
// return null;
// }
//
// FileListRequest sourcefileListRequest = buildFileRequest(sourceFilePath);
// FileListRequest targetfileListRequest = buildFileRequest(targetFilePath);
//
// //获取源文件列表 包含文件和文件夹
// List<FileItemResult> sourceFileItemList = obtainFileItemResultData(sourcefileListRequest);
// //获取目标文件列表 包含文件和文件夹
// List<FileItemResult> targetFileItemList = obtainFileItemResultData(targetfileListRequest);
// for (FileItemResult fileItemResult : sourceFileItemList) {
//
// String a1 = fileItemResult.getType() + fileItemResult.getName();
// FileItemResult targetFileItem = targetFileItemList.stream()
// .filter(t -> (t.getType() + t.getName()).equals(a1))
// .findFirst() // 获取第一个匹配项返回 Optional
// .orElse(null);
//
// // 检查对象存在
// if (targetFileItem != null) {
// // 循环处理文件 对比文件的MD5值
// if (fileItemResult.getType() == FileTypeEnum.FILE) {
// //源路径
// String sourcePath = sourceFilePath + "/" + fileItemResult.getName();
//
// //目标路径
// String targetPath = targetFilePath + "/" + fileItemResult.getName();
//
// //根据路径获取MD5值比较 如果相同则不进行操作 如果不同则重命名目标路径下的文件名称以及表结构 把现在源路径下的文件拷贝到目标路径下 新增数据库文件记录
// // 计算源文件MD5
// File sourceLocalFile = new File(sourcePath);
// String sourceLocalMD5 = calculateMD5Data(new FileInputStream(sourceLocalFile));
//
// // 计算源文件MD5
// File targetLocalFile = new File(targetPath);
// String targetLocalMD5 = calculateMD5Data(new FileInputStream(targetLocalFile));
//
// // 如果MD5值不相同则进行操作 //如果一致 则直接复制源文件到目标文件
// if (StringUtils.isNoneEmpty(sourceLocalMD5, targetLocalMD5) && !sourceLocalMD5.equals(targetLocalMD5)) {
// LOGGER.info("MD5值不一样的路径" + sourcePath);
// LOGGER.info("MD5值不一样的替换路径" + targetPath);
// //拷贝文件到目标目录 将原来的文件名更改以及将数据库表结构更改
// //更改目标路径下的文件名称
// String newTargetPath = renameFile(sourcePath);
// //将源目录文件 复制到 目标目录文件
// copyToDirectoryFile(newTargetPath, value + targetFolderPath + "/");
//
// } else {
// //将源目录文件 复制到 目标目录文件 todo这个地方是覆盖
// copyWithOverride(sourcePath, targetPath);
// }
// }
// } else {
// //如果为空对象不存在 则直接拷贝
// String sourcePath = value + sourceFilePath;
// //目标路径 就是源路径去掉/temporary的部分
// String targetPath = sourcePath.replace("/" + "temporary", "");
// //将源目录文件 复制到 目标目录文件
// copyFolderWithOverride(sourcePath, targetPath);
//
// }
// }
//
//
//
//
//
// return null;
// }
// 优化后的 MD5 计算方法线程安全 // 优化后的 MD5 计算方法线程安全
public String calculateMD5Data(InputStream inputStream) throws IOException, NoSuchAlgorithmException { public String calculateMD5Data(InputStream inputStream) throws IOException, NoSuchAlgorithmException {
@ -465,6 +483,7 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
} }
public static String renameFile(String originalPath) throws IOException { public static String renameFile(String originalPath) throws IOException {
// JSONObject jsonObject = new JSONObject()
File originalFile = new File(originalPath); File originalFile = new File(originalPath);
if (!originalFile.exists()) { if (!originalFile.exists()) {
throw new IOException("原文件不存在: " + originalPath); throw new IOException("原文件不存在: " + originalPath);
@ -488,6 +507,8 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
java.nio.file.Files.move(originalFilePath, newFilePath); java.nio.file.Files.move(originalFilePath, newFilePath);
System.out.println("重命名成功: " + originalPath + "" + newFilePath.toString()); System.out.println("重命名成功: " + originalPath + "" + newFilePath.toString());
return newFilePath.toString(); return newFilePath.toString();
// jsonObject.set("paht",newFilePath.toString());
// jsonObject.set("name",newFileName);
} }
private static void copyWithOverride(String source, String target) throws IOException { private static void copyWithOverride(String source, String target) throws IOException {
@ -553,12 +574,12 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
return fileListRequest; return fileListRequest;
} }
/********************************** /**********************************
* 用途说明: 修改专项文档管理-文档内容 * 用途说明: 修改专项文档管理-文档内容
* 参数说明 * 参数说明
* Files 文档内容 * Files 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败 * 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/ ***********************************/
@Override @Override
@Transactional(rollbackFor = Exception.class)// 添加事务注解遇到异常时回滚 @Transactional(rollbackFor = Exception.class)// 添加事务注解遇到异常时回滚
public boolean updateFiles(Files files) { public boolean updateFiles(Files files) {