|
24 | 24 | import com.datamate.datamanagement.infrastructure.persistence.repository.DatasetRepository; |
25 | 25 | import com.datamate.datamanagement.interfaces.converter.DatasetConverter; |
26 | 26 | import com.datamate.datamanagement.interfaces.dto.AddFilesRequest; |
27 | | -import com.datamate.datamanagement.interfaces.dto.CopyFilesRequest; |
28 | 27 | import com.datamate.datamanagement.interfaces.dto.CreateDirectoryRequest; |
29 | 28 | import com.datamate.datamanagement.interfaces.dto.UploadFileRequest; |
30 | 29 | import com.datamate.datamanagement.interfaces.dto.UploadFilesPreRequest; |
|
58 | 57 | import java.time.ZoneId; |
59 | 58 | import java.time.format.DateTimeFormatter; |
60 | 59 | import java.util.*; |
61 | | -import java.util.concurrent.CompletableFuture; |
62 | 60 | import java.util.function.Function; |
63 | 61 | import java.util.stream.Collectors; |
64 | 62 | import java.util.stream.Stream; |
@@ -664,11 +662,9 @@ public void renameFile(String datasetId, String fileId, RenameFileRequest reques |
664 | 662 | } |
665 | 663 |
|
666 | 664 | String originalFileName = file.getFileName(); |
667 | | - String baseName = originalFileName; |
668 | 665 | String extension = ""; |
669 | 666 | int dotIndex = originalFileName.lastIndexOf('.'); |
670 | 667 | if (dotIndex > 0 && dotIndex < originalFileName.length() - 1) { |
671 | | - baseName = originalFileName.substring(0, dotIndex); |
672 | 668 | extension = originalFileName.substring(dotIndex); // 包含点号,如 .jpg |
673 | 669 | } |
674 | 670 |
|
@@ -828,114 +824,102 @@ private void setDatasetFileId(DatasetFile datasetFile, Dataset dataset) { |
828 | 824 | } |
829 | 825 |
|
830 | 826 | /** |
831 | | - * 复制文件到数据集目录 |
| 827 | + * 添加文件到数据集(仅创建数据库记录,不执行文件系统操作) |
832 | 828 | * |
833 | 829 | * @param datasetId 数据集id |
834 | | - * @param req 复制文件请求 |
835 | | - * @return 复制的文件列表 |
| 830 | + * @param req 添加文件请求 |
| 831 | + * @return 添加的文件列表 |
836 | 832 | */ |
837 | 833 | @Transactional |
838 | | - public List<DatasetFile> copyFilesToDatasetDir(String datasetId, CopyFilesRequest req) { |
| 834 | + public List<DatasetFile> addFilesToDataset(String datasetId, AddFilesRequest req) { |
| 835 | + if (!req.isValidPrefix()) { |
| 836 | + throw BusinessException.of(DataManagementErrorCode.DIRECTORY_NOT_FOUND); |
| 837 | + } |
839 | 838 | Dataset dataset = datasetRepository.getById(datasetId); |
840 | 839 | BusinessAssert.notNull(dataset, SystemErrorCode.RESOURCE_NOT_FOUND); |
841 | | - List<DatasetFile> copiedFiles = new ArrayList<>(); |
| 840 | + List<DatasetFile> addedFiles = new ArrayList<>(); |
842 | 841 | List<DatasetFile> existDatasetFiles = datasetFileRepository.findAllByDatasetId(datasetId); |
843 | 842 | dataset.setFiles(existDatasetFiles); |
844 | | - for (String sourceFilePath : req.sourcePaths()) { |
845 | | - Path sourcePath = Paths.get(sourceFilePath); |
846 | | - if (!Files.exists(sourcePath) || !Files.isRegularFile(sourcePath)) { |
847 | | - log.warn("Source file does not exist or is not a regular file: {}", sourceFilePath); |
848 | | - continue; |
| 843 | + try { |
| 844 | + ObjectMapper objectMapper = new ObjectMapper(); |
| 845 | + |
| 846 | + for (AddFilesRequest.FileRequest file : req.getFiles()) { |
| 847 | + DatasetFile datasetFile = getDatasetFileForAdd(req, file, dataset, objectMapper); |
| 848 | + setDatasetFileId(datasetFile, dataset); |
| 849 | + dataset.addFile(datasetFile); |
| 850 | + addedFiles.add(datasetFile); |
| 851 | + addFile(file.getFilePath(), datasetFile.getFilePath(), req.isSoftAdd()); |
849 | 852 | } |
850 | | - String fileName = sourcePath.getFileName().toString(); |
851 | | - File sourceFile = sourcePath.toFile(); |
852 | | - LocalDateTime currentTime = LocalDateTime.now(); |
853 | | - DatasetFile datasetFile = DatasetFile.builder() |
854 | | - .id(UUID.randomUUID().toString()) |
855 | | - .datasetId(datasetId) |
856 | | - .fileName(fileName) |
857 | | - .fileType(AnalyzerUtils.getExtension(fileName)) |
858 | | - .fileSize(sourceFile.length()) |
859 | | - .filePath(Paths.get(dataset.getPath(), fileName).toString()) |
860 | | - .uploadTime(currentTime) |
861 | | - .lastAccessTime(currentTime) |
862 | | - .build(); |
863 | | - setDatasetFileId(datasetFile, dataset); |
864 | | - dataset.addFile(datasetFile); |
865 | | - copiedFiles.add(datasetFile); |
| 853 | + } catch (BusinessException e) { |
| 854 | + throw e; |
| 855 | + } catch (Exception e) { |
| 856 | + log.error("Failed to add file to dataset {}", dataset.getName(), e); |
| 857 | + throw BusinessException.of(SystemErrorCode.UNKNOWN_ERROR); |
866 | 858 | } |
867 | | - datasetFileRepository.saveOrUpdateBatch(copiedFiles, 100); |
| 859 | + |
| 860 | + datasetFileRepository.saveOrUpdateBatch(addedFiles, 100); |
868 | 861 | dataset.active(); |
869 | 862 | datasetRepository.updateById(dataset); |
870 | | - CompletableFuture.runAsync(() -> copyFilesToDatasetDir(req.sourcePaths(), dataset)); |
871 | | - return copiedFiles; |
| 863 | + return addedFiles; |
872 | 864 | } |
873 | 865 |
|
874 | | - private void copyFilesToDatasetDir(List<String> sourcePaths, Dataset dataset) { |
875 | | - for (String sourcePath : sourcePaths) { |
876 | | - Path sourceFilePath = Paths.get(sourcePath); |
877 | | - Path targetFilePath = Paths.get(dataset.getPath(), sourceFilePath.getFileName().toString()); |
878 | | - try { |
879 | | - Files.createDirectories(Path.of(dataset.getPath())); |
880 | | - Files.copy(sourceFilePath, targetFilePath); |
881 | | - } catch (IOException e) { |
882 | | - log.error("Failed to copy file from {} to {}", sourcePath, targetFilePath, e); |
883 | | - } |
| 866 | + private void addFile(String sourPath, String targetPath, boolean softAdd) { |
| 867 | + if (StringUtils.isBlank(sourPath) || StringUtils.isBlank(targetPath)) { |
| 868 | + return; |
884 | 869 | } |
885 | | - } |
| 870 | + Path source = Paths.get(sourPath).normalize(); |
| 871 | + Path target = Paths.get(targetPath).normalize(); |
886 | 872 |
|
887 | | - /** |
888 | | - * 添加文件到数据集(仅创建数据库记录,不执行文件系统操作) |
889 | | - * |
890 | | - * @param datasetId 数据集id |
891 | | - * @param req 添加文件请求 |
892 | | - * @return 添加的文件列表 |
893 | | - */ |
894 | | - @Transactional |
895 | | - public List<DatasetFile> addFilesToDataset(String datasetId, AddFilesRequest req) { |
896 | | - Dataset dataset = datasetRepository.getById(datasetId); |
897 | | - BusinessAssert.notNull(dataset, SystemErrorCode.RESOURCE_NOT_FOUND); |
898 | | - List<DatasetFile> addedFiles = new ArrayList<>(); |
899 | | - List<DatasetFile> existDatasetFiles = datasetFileRepository.findAllByDatasetId(datasetId); |
900 | | - dataset.setFiles(existDatasetFiles); |
| 873 | + // 检查源文件是否存在且为普通文件 |
| 874 | + if (!Files.exists(source) || !Files.isRegularFile(source)) { |
| 875 | + log.warn("Source file does not exist or is not a regular file: {}", sourPath); |
| 876 | + throw BusinessException.of(SystemErrorCode.FILE_SYSTEM_ERROR); |
| 877 | + } |
901 | 878 |
|
902 | | - boolean softAdd = req.softAdd(); |
903 | | - String metadata; |
904 | 879 | try { |
905 | | - Map<String, Boolean> metadataMap = Map.of("softAdd", softAdd); |
906 | | - ObjectMapper objectMapper = new ObjectMapper(); |
907 | | - metadata = objectMapper.writeValueAsString(metadataMap); |
908 | | - } catch (JsonProcessingException e) { |
909 | | - log.error("Failed to serialize metadataMap", e); |
910 | | - throw BusinessException.of(SystemErrorCode.UNKNOWN_ERROR); |
| 880 | + Path parent = target.getParent(); |
| 881 | + // 创建目标目录(如果需要) |
| 882 | + if (parent != null) { |
| 883 | + Files.createDirectories(parent); |
| 884 | + } |
| 885 | + Files.deleteIfExists(target); |
| 886 | + if (softAdd) { |
| 887 | + // 优先尝试创建硬链接,失败后尝试创建符号链接;若均失败抛出异常 |
| 888 | + try { |
| 889 | + Files.createLink(target, source); |
| 890 | + return; |
| 891 | + } catch (Throwable hardEx) { |
| 892 | + log.warn("create hard link failed from {} to {}: {}", source, target, hardEx.getMessage()); |
| 893 | + } |
| 894 | + Files.createSymbolicLink(target, source); |
| 895 | + } else { |
| 896 | + // 覆盖已存在的目标文件,保持与其他地方行为一致 |
| 897 | + Files.copy(source, target); |
| 898 | + } |
| 899 | + } catch (IOException e) { |
| 900 | + log.error("Failed to add file from {} to {}", source, target, e); |
| 901 | + throw BusinessException.of(SystemErrorCode.FILE_SYSTEM_ERROR); |
911 | 902 | } |
| 903 | + } |
912 | 904 |
|
913 | | - for (String sourceFilePath : req.sourcePaths()) { |
914 | | - Path sourcePath = Paths.get(sourceFilePath); |
915 | | - String fileName = sourcePath.getFileName().toString(); |
916 | | - File sourceFile = sourcePath.toFile(); |
917 | | - LocalDateTime currentTime = LocalDateTime.now(); |
| 905 | + private static DatasetFile getDatasetFileForAdd(AddFilesRequest req, AddFilesRequest.FileRequest file, |
| 906 | + Dataset dataset, ObjectMapper objectMapper) throws JsonProcessingException { |
| 907 | + Path sourcePath = Paths.get(file.getFilePath()); |
| 908 | + File sourceFile = sourcePath.toFile(); |
| 909 | + file.getMetadata().put("softAdd", req.isSoftAdd()); |
| 910 | + LocalDateTime currentTime = LocalDateTime.now(); |
| 911 | + String fileName = sourcePath.getFileName().toString(); |
918 | 912 |
|
919 | | - DatasetFile datasetFile = DatasetFile.builder() |
| 913 | + return DatasetFile.builder() |
920 | 914 | .id(UUID.randomUUID().toString()) |
921 | | - .datasetId(datasetId) |
| 915 | + .datasetId(dataset.getId()) |
922 | 916 | .fileName(fileName) |
923 | 917 | .fileType(AnalyzerUtils.getExtension(fileName)) |
924 | 918 | .fileSize(sourceFile.length()) |
925 | | - .filePath(sourceFilePath) |
| 919 | + .filePath(Paths.get(dataset.getPath(), req.getPrefix(), fileName).toString()) |
926 | 920 | .uploadTime(currentTime) |
927 | 921 | .lastAccessTime(currentTime) |
928 | | - .metadata(metadata) |
| 922 | + .metadata(objectMapper.writeValueAsString(file.getMetadata())) |
929 | 923 | .build(); |
930 | | - setDatasetFileId(datasetFile, dataset); |
931 | | - dataset.addFile(datasetFile); |
932 | | - addedFiles.add(datasetFile); |
933 | | - } |
934 | | - datasetFileRepository.saveOrUpdateBatch(addedFiles, 100); |
935 | | - dataset.active(); |
936 | | - datasetRepository.updateById(dataset); |
937 | | - // Note: addFilesToDataset only creates DB records, no file system operations |
938 | | - // If file copy is needed, use copyFilesToDatasetDir endpoint instead |
939 | | - return addedFiles; |
940 | 924 | } |
941 | 925 | } |
0 commit comments