package jnpf.fileStorage.dms;
|
|
import jnpf.base.ActionResult;
|
import jnpf.base.ActionResultCode;
|
import jnpf.dmsEntity.preview.model.DmsFilePreviewTicket;
|
import jnpf.dmsEntity.storage.form.DmsPersistentPdfGenerateForm;
|
import jnpf.dmsEntity.storage.vo.DmsPersistentPdfGenerateVO;
|
import jnpf.exception.DataException;
|
import jnpf.onlyoffice.DmsPreviewPdfApi;
|
import jnpf.onlyoffice.DmsPreviewPdfRequest;
|
import jnpf.util.JsonUtil;
|
import jnpf.util.TicketUtil;
|
import lombok.RequiredArgsConstructor;
|
import org.dromara.x.file.storage.core.FileInfo;
|
import org.dromara.x.file.storage.core.FileStorageService;
|
import org.dromara.x.file.storage.core.platform.MinioFileStorage;
|
import org.springframework.http.MediaType;
|
import org.springframework.stereotype.Service;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import java.io.ByteArrayInputStream;
|
import java.io.File;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.nio.file.Files;
|
import java.util.Collections;
|
import java.util.Locale;
|
import java.util.Objects;
|
|
@Service
|
@RequiredArgsConstructor
|
public class DmsPersistentPdfStorageService {
|
private static final long TICKET_TTL_SECONDS = 300L;
|
|
private final FileStorageService fileStorageService;
|
private final DmsPreviewPdfApi previewPdfApi;
|
|
public DmsPersistentPdfGenerateVO generate(DmsPersistentPdfGenerateForm form) {
|
validateSource(form);
|
String ticket = TicketUtil.createTicket(JsonUtil.getObjectToString(sourceTicket(form)),
|
TICKET_TTL_SECONDS);
|
FileInfo stored = null;
|
try {
|
ActionResult<byte[]> result = previewPdfApi.render(
|
new DmsPreviewPdfRequest(form.getFileVersionId(), ticket));
|
if (result == null || !ActionResultCode.SUCCESS.getCode().equals(result.getCode())
|
|| result.getData() == null || result.getData().length == 0) {
|
throw new DataException(result == null || result.getMsg() == null
|
? "持久化 PDF 生成失败" : result.getMsg());
|
}
|
MultipartFile pdf = new GeneratedPdf(form.getFileVersionId() + ".pdf", result.getData());
|
stored = fileStorageService.of(pdf)
|
.setPlatform(form.getStoragePlatform())
|
.setPath("dms-derived/pdf/" + form.getFileVersionId() + "/")
|
.setSaveFilename(form.getSourceChecksumSha256() + ".pdf")
|
.setOriginalFilename(pdf.getOriginalFilename())
|
.setHashCalculatorSha256()
|
.upload();
|
if (stored == null || stored.getSize() == null || stored.getSize() <= 0
|
|| stored.getHashInfo() == null || stored.getHashInfo().getSha256() == null) {
|
deleteQuietly(stored);
|
throw new DataException("持久化 PDF 保存失败");
|
}
|
DmsPersistentPdfGenerateVO value = new DmsPersistentPdfGenerateVO();
|
value.setObjectKey(empty(stored.getPath()) + stored.getFilename());
|
value.setSizeBytes(stored.getSize());
|
value.setChecksumSha256(stored.getHashInfo().getSha256().toLowerCase(Locale.ROOT));
|
value.setSourceChecksumSha256(form.getSourceChecksumSha256());
|
return value;
|
} finally {
|
TicketUtil.deleteTicket(ticket);
|
}
|
}
|
|
private void validateSource(DmsPersistentPdfGenerateForm form) {
|
String extension = extension(form.getFileName());
|
if (!"doc".equals(extension) && !"docx".equals(extension)) {
|
throw new DataException("仅支持为 Word 文件生成持久化 PDF");
|
}
|
MinioFileStorage storage = fileStorageService.getFileStorageVerify(form.getStoragePlatform());
|
if (!Objects.equals(storage.getBucketName(), form.getBucketName())) {
|
throw new DataException("DMS 原文件存储桶与当前配置不匹配");
|
}
|
}
|
|
private DmsFilePreviewTicket sourceTicket(DmsPersistentPdfGenerateForm form) {
|
DmsFilePreviewTicket ticket = new DmsFilePreviewTicket();
|
ticket.setScope(DmsFilePreviewTicket.SCOPE);
|
ticket.setTenantId(form.getTenantId());
|
ticket.setUserId("dms-pdf-generator");
|
ticket.setFileVersionId(form.getFileVersionId());
|
ticket.setFileName(form.getFileName());
|
ticket.setMimeType(form.getMimeType());
|
ticket.setSizeBytes(form.getSizeBytes());
|
ticket.setStoragePlatform(form.getStoragePlatform());
|
ticket.setBucketName(form.getBucketName());
|
ticket.setBasePath(empty(form.getBasePath()));
|
ticket.setObjectPath(form.getObjectPath());
|
ticket.setObjectName(form.getObjectName());
|
ticket.setWatermarks(Collections.emptyList());
|
ticket.setExpiresAt(System.currentTimeMillis() + TICKET_TTL_SECONDS * 1000L);
|
return ticket;
|
}
|
|
private void deleteQuietly(FileInfo stored) {
|
if (stored == null) return;
|
try { fileStorageService.delete(stored); }
|
catch (RuntimeException ignored) { }
|
}
|
|
private String extension(String fileName) {
|
int dot = fileName == null ? -1 : fileName.lastIndexOf('.');
|
return dot < 0 ? "" : fileName.substring(dot + 1).toLowerCase(Locale.ROOT);
|
}
|
|
private String empty(String value) { return value == null ? "" : value; }
|
|
private static final class GeneratedPdf implements MultipartFile {
|
private final String fileName;
|
private final byte[] content;
|
|
private GeneratedPdf(String fileName, byte[] content) {
|
this.fileName = fileName;
|
this.content = content;
|
}
|
|
@Override public String getName() { return "file"; }
|
@Override public String getOriginalFilename() { return fileName; }
|
@Override public String getContentType() { return MediaType.APPLICATION_PDF_VALUE; }
|
@Override public boolean isEmpty() { return content.length == 0; }
|
@Override public long getSize() { return content.length; }
|
@Override public byte[] getBytes() { return content.clone(); }
|
@Override public InputStream getInputStream() { return new ByteArrayInputStream(content); }
|
@Override public void transferTo(File destination) throws IOException {
|
Files.write(destination.toPath(), content);
|
}
|
}
|
}
|