From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-file/jnpf-file-storage/src/main/java/jnpf/fileStorage/dms/DmsFileStorageService.java |  299 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 299 insertions(+), 0 deletions(-)

diff --git a/jnpf-file/jnpf-file-storage/src/main/java/jnpf/fileStorage/dms/DmsFileStorageService.java b/jnpf-file/jnpf-file-storage/src/main/java/jnpf/fileStorage/dms/DmsFileStorageService.java
new file mode 100644
index 0000000..46e067a
--- /dev/null
+++ b/jnpf-file/jnpf-file-storage/src/main/java/jnpf/fileStorage/dms/DmsFileStorageService.java
@@ -0,0 +1,299 @@
+package jnpf.fileStorage.dms;
+
+import jnpf.base.ActionResult;
+import jnpf.base.ActionResultCode;
+import jnpf.config.ConfigValueUtil;
+import jnpf.constant.MsgCode;
+import jnpf.dms.DmsResourceApi;
+import jnpf.dmsEntity.storage.form.DmsFileRevisionRegisterForm;
+import jnpf.dmsEntity.storage.form.DmsFileUploadRegisterForm;
+import jnpf.dmsEntity.storage.vo.DmsFileUploadVO;
+import jnpf.exception.DataException;
+import jnpf.util.OptimizeUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.UpUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageService;
+import org.dromara.x.file.storage.core.hash.HashInfo;
+import org.dromara.x.file.storage.core.platform.MinioFileStorage;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.Objects;
+import java.util.UUID;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class DmsFileStorageService {
+    static final String STORAGE_PLATFORM = "seaweedfs-1";
+    static final String SERVICE_ID = "jnpf-file";
+
+    private final FileStorageService fileStorageService;
+    private final DmsResourceApi dmsResourceApi;
+    private final ConfigValueUtil configValueUtil;
+
+    public DmsFileUploadVO upload(UUID folderId, String sourceId, String documentNo,
+                                  String documentName, String documentType,
+                                  String responsibleDeptId, String versionLabel,
+                                  String preparedBy, LocalDate preparedOn, MultipartFile file) {
+        validate(sourceId, documentNo, documentName, documentType, responsibleDeptId,
+                versionLabel, preparedBy, preparedOn, file);
+        String originalFilename = safeFilename(file.getOriginalFilename());
+        String extension = UpUtil.getFileType(file);
+        if (!OptimizeUtil.fileType(configValueUtil.getAllowUploadFileType(), extension)) {
+            throw new DataException(MsgCode.FA017.get());
+        }
+
+        UUID documentId = UuidV7Generator.generate();
+        UUID fileVersionId = UuidV7Generator.generate();
+        UUID fileObjectId = UuidV7Generator.generate();
+        String objectPath = objectPath(documentId);
+        String objectName = fileVersionId + (StringUtil.isEmpty(extension) ? "" : "." + extension);
+
+        FileInfo stored = fileStorageService.of(file)
+                .setPlatform(STORAGE_PLATFORM)
+                .setPath(objectPath)
+                .setSaveFilename(objectName)
+                .setOriginalFilename(originalFilename)
+                .setHashCalculatorSha256()
+                .upload();
+        if (stored == null || stored.getHashInfo() == null
+                || StringUtil.isEmpty(stored.getHashInfo().getSha256())) {
+            deleteQuietly(stored);
+            throw new DataException("SeaweedFS 涓婁紶澶辫触鎴栨湭鐢熸垚 SHA-256");
+        }
+
+        DmsFileUploadRegisterForm form = registration(folderId, sourceId, documentNo,
+                documentName, documentType, responsibleDeptId, versionLabel, preparedBy,
+                preparedOn, originalFilename, documentId, fileVersionId, fileObjectId, stored);
+        try {
+            ActionResult<DmsFileUploadVO> result = dmsResourceApi.registerUpload(SERVICE_ID, form);
+            if (result == null || !ActionResultCode.SUCCESS.getCode().equals(result.getCode())
+                    || result.getData() == null) {
+                throw new DataException(result == null ? "DMS 涓婁紶鐧昏鏃犲搷搴�" : result.getMsg());
+            }
+            if (!sameStoredObject(result.getData(), stored)) {
+                deleteQuietly(stored);
+            }
+            return result.getData();
+        } catch (RuntimeException exception) {
+            deleteQuietly(stored);
+            throw exception;
+        }
+    }
+
+    public DmsFileUploadVO revise(UUID documentId, UUID baseFileVersionId, String sourceId,
+                                  String versionLabel, String preparedBy, LocalDate preparedOn,
+                                  String revisionReason, MultipartFile file) {
+        validateRevision(documentId, baseFileVersionId, sourceId, versionLabel, preparedBy,
+                preparedOn, revisionReason, file);
+        String originalFilename = safeFilename(file.getOriginalFilename());
+        String extension = UpUtil.getFileType(file);
+        if (!OptimizeUtil.fileType(configValueUtil.getAllowUploadFileType(), extension)) {
+            throw new DataException(MsgCode.FA017.get());
+        }
+
+        UUID fileVersionId = UuidV7Generator.generate();
+        UUID fileObjectId = UuidV7Generator.generate();
+        String objectPath = objectPath(documentId);
+        String objectName = fileVersionId + (StringUtil.isEmpty(extension) ? "" : "." + extension);
+
+        FileInfo stored = fileStorageService.of(file)
+                .setPlatform(STORAGE_PLATFORM)
+                .setPath(objectPath)
+                .setSaveFilename(objectName)
+                .setOriginalFilename(originalFilename)
+                .setHashCalculatorSha256()
+                .upload();
+        if (stored == null || stored.getHashInfo() == null
+                || StringUtil.isEmpty(stored.getHashInfo().getSha256())) {
+            deleteQuietly(stored);
+            throw new DataException("SeaweedFS 涓婁紶澶辫触鎴栨湭鐢熸垚 SHA-256");
+        }
+
+        DmsFileRevisionRegisterForm form = revisionRegistration(documentId, baseFileVersionId,
+                fileVersionId, fileObjectId, sourceId, versionLabel, preparedBy, preparedOn,
+                revisionReason, originalFilename, stored);
+        try {
+            ActionResult<DmsFileUploadVO> result = dmsResourceApi.registerRevision(SERVICE_ID, form);
+            if (result == null || !ActionResultCode.SUCCESS.getCode().equals(result.getCode())
+                    || result.getData() == null) {
+                throw new DataException(result == null ? "DMS 淇鐧昏鏃犲搷搴�" : result.getMsg());
+            }
+            if (!sameStoredObject(result.getData(), stored)) {
+                deleteQuietly(stored);
+            }
+            return result.getData();
+        } catch (RuntimeException exception) {
+            deleteQuietly(stored);
+            throw exception;
+        }
+    }
+
+    private DmsFileUploadRegisterForm registration(UUID folderId, String sourceId,
+                                                   String documentNo, String documentName,
+                                                   String documentType, String responsibleDeptId,
+                                                   String versionLabel, String preparedBy,
+                                                   LocalDate preparedOn, String originalFilename,
+                                                   UUID documentId,
+                                                   UUID fileVersionId, UUID fileObjectId,
+                                                   FileInfo stored) {
+        MinioFileStorage storage = fileStorageService.getFileStorage(STORAGE_PLATFORM);
+        HashInfo hashInfo = stored.getHashInfo();
+        DmsFileUploadRegisterForm form = new DmsFileUploadRegisterForm();
+        form.setDocumentId(documentId);
+        form.setFileVersionId(fileVersionId);
+        form.setFileObjectId(fileObjectId);
+        form.setFolderId(folderId);
+        form.setDocumentNo(documentNo.trim());
+        form.setDocumentName(documentName.trim());
+        form.setDocumentType(documentType.trim());
+        form.setResponsibleDeptId(responsibleDeptId.trim());
+        form.setVersionLabel(versionLabel.trim());
+        form.setFileName(originalFilename);
+        form.setMimeType(trimToNull(stored.getContentType()));
+        form.setSizeBytes(stored.getSize());
+        form.setChecksumSha256(hashInfo.getSha256());
+        form.setPreparedBy(preparedBy.trim());
+        form.setPreparedOn(preparedOn);
+        form.setStoragePlatform(stored.getPlatform());
+        form.setBucketName(storage.getBucketName());
+        form.setBasePath(trimToEmpty(stored.getBasePath()));
+        form.setObjectPath(stored.getPath());
+        form.setObjectName(stored.getFilename());
+        form.setSourceId(sourceId.trim());
+        return form;
+    }
+
+    private DmsFileRevisionRegisterForm revisionRegistration(UUID documentId,
+                                                              UUID baseFileVersionId,
+                                                              UUID fileVersionId,
+                                                              UUID fileObjectId,
+                                                              String sourceId,
+                                                              String versionLabel,
+                                                              String preparedBy,
+                                                              LocalDate preparedOn,
+                                                              String revisionReason,
+                                                              String originalFilename,
+                                                              FileInfo stored) {
+        MinioFileStorage storage = fileStorageService.getFileStorage(STORAGE_PLATFORM);
+        HashInfo hashInfo = stored.getHashInfo();
+        DmsFileRevisionRegisterForm form = new DmsFileRevisionRegisterForm();
+        form.setDocumentId(documentId);
+        form.setBaseFileVersionId(baseFileVersionId);
+        form.setFileVersionId(fileVersionId);
+        form.setFileObjectId(fileObjectId);
+        form.setVersionLabel(versionLabel.trim());
+        form.setFileName(originalFilename);
+        form.setMimeType(trimToNull(stored.getContentType()));
+        form.setSizeBytes(stored.getSize());
+        form.setChecksumSha256(hashInfo.getSha256());
+        form.setPreparedBy(preparedBy.trim());
+        form.setPreparedOn(preparedOn);
+        form.setRevisionReason(revisionReason.trim());
+        form.setStoragePlatform(stored.getPlatform());
+        form.setBucketName(storage.getBucketName());
+        form.setBasePath(trimToEmpty(stored.getBasePath()));
+        form.setObjectPath(stored.getPath());
+        form.setObjectName(stored.getFilename());
+        form.setSourceId(sourceId.trim());
+        return form;
+    }
+
+    private boolean sameStoredObject(DmsFileUploadVO registered, FileInfo stored) {
+        return Objects.equals(registered.getStoragePlatform(), stored.getPlatform())
+                && Objects.equals(registered.getBasePath(), trimToEmpty(stored.getBasePath()))
+                && Objects.equals(registered.getObjectPath(), stored.getPath())
+                && Objects.equals(registered.getObjectName(), stored.getFilename());
+    }
+
+    private String objectPath(UUID documentId) {
+        return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/"))
+                + documentId + "/";
+    }
+
+    private String safeFilename(String value) {
+        if (value == null || value.trim().isEmpty()) {
+            throw new DataException("鏂囦欢鍚嶄笉鑳戒负绌�");
+        }
+        String normalized = value.replace('\\', '/');
+        String filename = Paths.get(normalized).getFileName().toString().trim();
+        if (filename.isEmpty() || filename.length() > 300) {
+            throw new DataException("鏂囦欢鍚嶉暱搴﹀繀椤诲湪 1 鍒� 300 涔嬮棿");
+        }
+        return filename;
+    }
+
+    private void validate(String sourceId, String documentNo, String documentName,
+                          String documentType, String responsibleDeptId, String versionLabel,
+                          String preparedBy, LocalDate preparedOn, MultipartFile file) {
+        if (file == null || file.isEmpty()) {
+            throw new DataException("涓婁紶鏂囦欢涓嶈兘涓虹┖");
+        }
+        requireText(sourceId, "sourceId", 160);
+        requireText(documentNo, "鏂囦欢缂栧彿", 200);
+        requireText(documentName, "鏂囦欢鍚嶇О", 300);
+        requireText(documentType, "鏂囦欢绫诲瀷", 100);
+        requireText(responsibleDeptId, "褰掑睘閮ㄩ棬", 100);
+        requireText(versionLabel, "鐗堟湰鍙�", 50);
+        requireText(preparedBy, "鍒跺畾浜�", 100);
+        if (preparedOn == null) {
+            throw new DataException("鍒跺畾鏃ユ湡涓嶈兘涓虹┖");
+        }
+        fileStorageService.getFileStorageVerify(STORAGE_PLATFORM);
+    }
+
+    private void validateRevision(UUID documentId, UUID baseFileVersionId, String sourceId,
+                                  String versionLabel, String preparedBy, LocalDate preparedOn,
+                                  String revisionReason, MultipartFile file) {
+        if (documentId == null || baseFileVersionId == null) {
+            throw new DataException("鏂囦欢鍙婂綋鍓嶇増鏈笉鑳戒负绌�");
+        }
+        if (file == null || file.isEmpty()) {
+            throw new DataException("淇鏂囦欢涓嶈兘涓虹┖");
+        }
+        requireText(sourceId, "sourceId", 120);
+        requireText(versionLabel, "鏂扮増鏈彿", 50);
+        requireText(preparedBy, "鍒跺畾浜�", 100);
+        requireText(revisionReason, "淇鍘熷洜", 1000);
+        if (preparedOn == null) {
+            throw new DataException("鍒跺畾鏃ユ湡涓嶈兘涓虹┖");
+        }
+        fileStorageService.getFileStorageVerify(STORAGE_PLATFORM);
+    }
+
+    private void requireText(String value, String label, int maxLength) {
+        if (value == null || value.trim().isEmpty() || value.trim().length() > maxLength) {
+            throw new DataException(label + "闀垮害蹇呴』鍦� 1 鍒� " + maxLength + " 涔嬮棿");
+        }
+    }
+
+    private String trimToEmpty(String value) {
+        return value == null ? "" : value.trim();
+    }
+
+    private String trimToNull(String value) {
+        return value == null || value.trim().isEmpty() ? null : value.trim();
+    }
+
+    private void deleteQuietly(FileInfo stored) {
+        if (stored == null) {
+            return;
+        }
+        try {
+            if (!fileStorageService.delete(stored)) {
+                log.error("DMS 涓婁紶琛ュ伩鍒犻櫎澶辫触: platform={}, path={}, filename={}",
+                        stored.getPlatform(), stored.getPath(), stored.getFilename());
+            }
+        } catch (Exception exception) {
+            log.error("DMS 涓婁紶琛ュ伩鍒犻櫎寮傚父: platform={}, path={}, filename={}",
+                    stored.getPlatform(), stored.getPath(), stored.getFilename(), exception);
+        }
+    }
+}

--
Gitblit v1.8.0