fix:批量同步节点下的普通文件夹

This commit is contained in:
2026-01-24 17:32:10 +08:00
parent 556c0e62af
commit b86b279a1f
4 changed files with 149 additions and 7 deletions

View File

@@ -7,6 +7,7 @@ import com.sdm.common.entity.req.data.*;
import com.sdm.common.entity.req.system.LaunchApproveReq;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.entity.resp.data.BatchAddFileInfoResp;
import com.sdm.common.entity.resp.data.BatchCreateNormalDirResp;
import com.sdm.common.entity.resp.data.ChunkUploadMinioFileResp;
import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
import com.sdm.common.feign.inter.data.IDataFeignClient;
@@ -63,7 +64,7 @@ public class DataFileController implements IDataFeignClient {
}
/**
* 批量创建文件夹(支持多级树形结构)
* 针对 项目节点目录树 的导入,所有节点必须是节点类型,不适用于批量创建普通文件夹
*
* @param req 批量创建请求
* @return 创建成功的文件夹ID列表
@@ -74,6 +75,18 @@ public class DataFileController implements IDataFeignClient {
return IDataFileService.batchCreateDir(req);
}
/**
* 批量创建普通文件夹
*
* @param req 批量创建请求
* @return 创建结果(包含成功和失败列表)
*/
@PostMapping("/batchCreateNormalDirs")
@Operation(summary = "批量创建普通文件夹", description = "在指定父目录下批量创建多个普通文件夹")
public SdmResponse<BatchCreateNormalDirResp> batchCreateNormalDirs(@RequestBody @Validated BatchCreateNormalDirReq req) {
return IDataFileService.batchCreateNormalDirs(req);
}
/**
* 因为审批的都是文件 所以这个审批回调方法可以公用
* @param req
@@ -627,4 +640,4 @@ public class DataFileController implements IDataFeignClient {
return IDataFileService.copyFileToTask(req);
}
}
}

View File

@@ -19,7 +19,12 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.InputStream;
import java.util.List;
import com.sdm.common.entity.req.data.BatchCreateNormalDirReq;
import com.sdm.common.entity.resp.data.BatchCreateNormalDirResp;
/**
* 数据文件服务接口
*/
@Service
public interface IDataFileService {
@@ -394,4 +399,13 @@ public interface IDataFileService {
default SdmResponse<FileMetadataInfoResp> queryFileIdByNodeId(QueryFileIdReq queryFileIdReq){return null;};
/**
* 批量创建普通目录
* @param req 批量创建普通目录请求参数
* @return 创建结果响应(包含成功列表和失败列表)
*/
default SdmResponse<BatchCreateNormalDirResp> batchCreateNormalDirs(BatchCreateNormalDirReq req) {
return null;
}
}

View File

@@ -157,10 +157,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
@Autowired
private LocalFileService localFileService;
// @Override
// public String getType() {
// return type;
// }
private static final String TEMP_FILE_PATH = "/usr/local/nginx/html/storage/";
@@ -3824,4 +3821,122 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
return levelNodes;
}
/**
* 批量创建普通目录
*/
@Override
@Transactional(rollbackFor = Exception.class)
public SdmResponse<BatchCreateNormalDirResp> batchCreateNormalDirs(BatchCreateNormalDirReq req) {
// 1. 基础校验
if (req.getParentId() == null) {
return SdmResponse.failed("父文件夹ID不能为空");
}
if (CollectionUtils.isEmpty(req.getFolderNames())) {
return SdmResponse.failed("文件夹名称列表不能为空");
}
// 2. 父目录校验与权限检查
FileMetadataInfo parentDir = fileMetadataInfoService.getById(req.getParentId());
if (parentDir == null) {
return SdmResponse.failed("父文件夹不存在");
}
// 权限检查(需要写入权限)
boolean hasWritePermission = fileUserPermissionService.hasFilePermission(req.getParentId(), ThreadLocalContext.getUserId(), FilePermissionEnum.WRITE);
if (!hasWritePermission) {
return SdmResponse.failed("没有写入权限");
}
BatchCreateNormalDirResp resp = new BatchCreateNormalDirResp();
// 去重并过滤空名
List<String> validFolderNames = req.getFolderNames().stream()
.filter(name -> name != null && !name.trim().isEmpty())
.distinct()
.collect(Collectors.toList());
if (validFolderNames.isEmpty()) {
return SdmResponse.failed("有效文件夹名称为空");
}
// 3. 检查数据库中是否已存在同名目录
List<FileMetadataInfo> existingFiles = fileMetadataInfoService.lambdaQuery()
.eq(FileMetadataInfo::getParentId, req.getParentId())
.eq(FileMetadataInfo::getTenantId, ThreadLocalContext.getTenantId())
.eq(FileMetadataInfo::getDataType, DataTypeEnum.DIRECTORY.getValue())
.in(FileMetadataInfo::getOriginalName, validFolderNames)
.list();
Set<String> existingNames = existingFiles.stream()
.map(FileMetadataInfo::getOriginalName)
.collect(Collectors.toSet());
List<String> toCreateNames = new ArrayList<>();
for (String name : validFolderNames) {
if (existingNames.contains(name)) {
resp.addFailure(name, "文件夹已存在");
} else {
toCreateNames.add(name);
}
}
if (toCreateNames.isEmpty()) {
return SdmResponse.success(resp);
}
// 4. 准备创建数据
List<FileMetadataInfo> newDirs = new ArrayList<>();
List<String> minioKeys = new ArrayList<>();
String parentObjectKey = parentDir.getObjectKey();
// 确保parentObjectKey以/结尾
if (!parentObjectKey.endsWith("/")) {
parentObjectKey += "/";
}
for (String name : toCreateNames) {
// 构造对象Key
String objectKey = getDirMinioObjectKey(parentObjectKey + name);
// 创建元数据对象 (复用现有的createDirectoryMetadata方法)
FileMetadataInfo dirInfo = createDirectoryMetadata(
objectKey, name, false, parentDir.getId(),
null, null, parentDir.getDirType());
newDirs.add(dirInfo);
minioKeys.add(objectKey);
}
try {
// 5. MinIO批量创建
minioService.batchCreateDirectories(minioKeys, minioService.getCurrentTenantBucketName());
// 6. 数据库批量插入
fileMetadataInfoService.saveBatch(newDirs);
// 7. 批量添加权限
List<FileUserPermission> permissions = newDirs.stream().map(dir -> {
FileUserPermission p = new FileUserPermission();
p.setTFilemetaId(dir.getId());
p.setPermission(FilePermissionEnum.ALL.getValue());
p.setUserId(ThreadLocalContext.getUserId());
p.setTenantId(ThreadLocalContext.getTenantId());
return p;
}).collect(Collectors.toList());
fileUserPermissionService.saveBatch(permissions, 500);
// 填充成功列表
for (FileMetadataInfo dir : newDirs) {
resp.addSuccess(dir.getId(), dir.getOriginalName());
}
} catch (Exception e) {
log.error("批量创建普通文件夹失败", e);
// 补偿删除MinIO目录
compensateDeleteMinioKeys(minioKeys);
throw new RuntimeException("批量创建失败: " + e.getMessage(), e);
}
return SdmResponse.success(resp);
}
}