You've already forked DataMate
refactor(data-management): 优化知识项目预览服务的文件转换逻辑
- 移除 docx4j 相关依赖和转换方法 - 统一 office 文件转换为 pdf 的处理方式,全部使用 libreoffice - 删除单独的 docx 到 pdf 转换方法 - 重命名转换方法为 convertOfficeToPdfByLibreOffice - 增强路径解析逻辑,添加多种候选路径处理 - 添加路径安全性验证和规范化处理 - 新增 extractRelativePathFromSegment 和 normalizeRelativePathValue 辅助方法 - 改进文件存在性检查和路径构建逻辑
This commit is contained in:
@@ -8,14 +8,11 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.docx4j.Docx4J;
|
||||
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -82,11 +79,7 @@ public class KnowledgeItemPreviewAsyncService {
|
||||
ensureParentDirectory(targetPath);
|
||||
|
||||
try {
|
||||
if ("docx".equals(extension)) {
|
||||
convertDocxToPdf(sourcePath, targetPath);
|
||||
} else {
|
||||
convertDocToPdfByLibreOffice(sourcePath, targetPath);
|
||||
}
|
||||
convertOfficeToPdfByLibreOffice(sourcePath, targetPath);
|
||||
updatePreviewStatus(item, KnowledgeItemPreviewStatus.READY, previewRelativePath, null);
|
||||
} catch (Exception e) {
|
||||
log.error("preview convert failed, itemId: {}", item.getId(), e);
|
||||
@@ -94,14 +87,7 @@ public class KnowledgeItemPreviewAsyncService {
|
||||
}
|
||||
}
|
||||
|
||||
private void convertDocxToPdf(Path sourcePath, Path targetPath) throws Exception {
|
||||
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(sourcePath.toFile());
|
||||
try (OutputStream outputStream = Files.newOutputStream(targetPath)) {
|
||||
Docx4J.toPDF(wordMLPackage, outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertDocToPdfByLibreOffice(Path sourcePath, Path targetPath) throws Exception {
|
||||
private void convertOfficeToPdfByLibreOffice(Path sourcePath, Path targetPath) throws Exception {
|
||||
Path outputDir = targetPath.getParent();
|
||||
ensureParentDirectory(targetPath);
|
||||
List<String> command = List.of(
|
||||
@@ -234,8 +220,70 @@ public class KnowledgeItemPreviewAsyncService {
|
||||
}
|
||||
|
||||
private Path resolveKnowledgeItemStoragePath(String relativePath) {
|
||||
String normalizedRelativePath = StringUtils.defaultString(relativePath).replace("/", java.io.File.separator);
|
||||
if (StringUtils.isBlank(relativePath)) {
|
||||
throw new IllegalArgumentException("invalid knowledge item path");
|
||||
}
|
||||
String normalizedInput = relativePath.replace("\\", PATH_SEPARATOR).trim();
|
||||
Path root = resolveUploadRootPath();
|
||||
java.util.LinkedHashSet<Path> candidates = new java.util.LinkedHashSet<>();
|
||||
|
||||
Path inputPath = Paths.get(normalizedInput.replace(PATH_SEPARATOR, java.io.File.separator));
|
||||
if (inputPath.isAbsolute()) {
|
||||
Path normalizedAbsolute = inputPath.toAbsolutePath().normalize();
|
||||
if (normalizedAbsolute.startsWith(root)) {
|
||||
candidates.add(normalizedAbsolute);
|
||||
}
|
||||
String segmentRelativePath = extractRelativePathFromSegment(normalizedInput, KNOWLEDGE_ITEM_UPLOAD_DIR);
|
||||
if (StringUtils.isNotBlank(segmentRelativePath)) {
|
||||
candidates.add(buildKnowledgeItemStoragePath(root, segmentRelativePath));
|
||||
}
|
||||
if (candidates.isEmpty()) {
|
||||
throw new IllegalArgumentException("invalid knowledge item path");
|
||||
}
|
||||
} else {
|
||||
String normalizedRelative = normalizeRelativePathValue(normalizedInput);
|
||||
if (StringUtils.isNotBlank(normalizedRelative)) {
|
||||
candidates.add(buildKnowledgeItemStoragePath(root, normalizedRelative));
|
||||
}
|
||||
String segmentRelativePath = extractRelativePathFromSegment(normalizedInput, KNOWLEDGE_ITEM_UPLOAD_DIR);
|
||||
if (StringUtils.isNotBlank(segmentRelativePath)) {
|
||||
candidates.add(buildKnowledgeItemStoragePath(root, segmentRelativePath));
|
||||
}
|
||||
if (StringUtils.isNotBlank(normalizedRelative)
|
||||
&& !normalizedRelative.startsWith(KNOWLEDGE_ITEM_UPLOAD_DIR + PATH_SEPARATOR)
|
||||
&& !normalizedRelative.equals(KNOWLEDGE_ITEM_UPLOAD_DIR)) {
|
||||
candidates.add(buildKnowledgeItemStoragePath(root, KNOWLEDGE_ITEM_UPLOAD_DIR + PATH_SEPARATOR + normalizedRelative));
|
||||
}
|
||||
}
|
||||
|
||||
if (root.getFileName() != null && KNOWLEDGE_ITEM_UPLOAD_DIR.equals(root.getFileName().toString())) {
|
||||
String normalizedRelative = normalizeRelativePathValue(normalizedInput);
|
||||
if (StringUtils.isNotBlank(normalizedRelative)
|
||||
&& normalizedRelative.startsWith(KNOWLEDGE_ITEM_UPLOAD_DIR + PATH_SEPARATOR)) {
|
||||
String withoutPrefix = normalizedRelative.substring(KNOWLEDGE_ITEM_UPLOAD_DIR.length() + PATH_SEPARATOR.length());
|
||||
if (StringUtils.isNotBlank(withoutPrefix)) {
|
||||
candidates.add(buildKnowledgeItemStoragePath(root, withoutPrefix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Path fallback = null;
|
||||
for (Path candidate : candidates) {
|
||||
if (fallback == null) {
|
||||
fallback = candidate;
|
||||
}
|
||||
if (Files.exists(candidate) && Files.isRegularFile(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
if (fallback == null) {
|
||||
throw new IllegalArgumentException("invalid knowledge item path");
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private Path buildKnowledgeItemStoragePath(Path root, String relativePath) {
|
||||
String normalizedRelativePath = StringUtils.defaultString(relativePath).replace(PATH_SEPARATOR, java.io.File.separator);
|
||||
Path target = root.resolve(normalizedRelativePath).toAbsolutePath().normalize();
|
||||
if (!target.startsWith(root)) {
|
||||
throw new IllegalArgumentException("invalid knowledge item path");
|
||||
@@ -243,6 +291,36 @@ public class KnowledgeItemPreviewAsyncService {
|
||||
return target;
|
||||
}
|
||||
|
||||
private String extractRelativePathFromSegment(String rawPath, String segment) {
|
||||
if (StringUtils.isBlank(rawPath) || StringUtils.isBlank(segment)) {
|
||||
return null;
|
||||
}
|
||||
String normalized = rawPath.replace("\\", PATH_SEPARATOR).trim();
|
||||
while (normalized.startsWith(PATH_SEPARATOR)) {
|
||||
normalized = normalized.substring(1);
|
||||
}
|
||||
String segmentPrefix = segment + PATH_SEPARATOR;
|
||||
int index = normalized.indexOf(segmentPrefix);
|
||||
if (index < 0) {
|
||||
return segment.equals(normalized) ? segment : null;
|
||||
}
|
||||
return normalizeRelativePathValue(normalized.substring(index));
|
||||
}
|
||||
|
||||
private String normalizeRelativePathValue(String relativePath) {
|
||||
if (StringUtils.isBlank(relativePath)) {
|
||||
return "";
|
||||
}
|
||||
String normalized = relativePath.replace("\\", PATH_SEPARATOR).trim();
|
||||
while (normalized.startsWith(PATH_SEPARATOR)) {
|
||||
normalized = normalized.substring(1);
|
||||
}
|
||||
while (normalized.endsWith(PATH_SEPARATOR)) {
|
||||
normalized = normalized.substring(0, normalized.length() - 1);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private Path resolveUploadRootPath() {
|
||||
String uploadDir = dataManagementProperties.getFileStorage().getUploadDir();
|
||||
return Paths.get(uploadDir).toAbsolutePath().normalize();
|
||||
|
||||
Reference in New Issue
Block a user