5.0版本 发布 新增 cadviewer转换方法

This commit is contained in:
高雄
2026-01-22 11:28:25 +08:00
parent 7dc0469b30
commit e43f10138f
1022 changed files with 293112 additions and 3187 deletions

View File

@@ -6,10 +6,7 @@ import cn.keking.model.ReturnResponse;
import cn.keking.service.CadToPdfService;
import cn.keking.service.FileHandlerService;
import cn.keking.service.FilePreview;
import cn.keking.utils.DownloadUtils;
import cn.keking.utils.FileConvertStatusManager;
import cn.keking.utils.KkFileUtils;
import cn.keking.utils.WebUtils;
import cn.keking.utils.*;
import cn.keking.web.filter.BaseUrlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -78,12 +75,14 @@ public class CadFilePreviewImpl implements FilePreview {
}
String filePath = response.getContent();
int refreshSchedule = ConfigConstants.getTime();
if (StringUtils.hasText(outFilePath)) {
try {
// 启动异步转换,并添加回调处理
startAsyncConversion(filePath, outFilePath, cacheName, fileAttribute);
// 返回等待页面
model.addAttribute("fileName", fileName);
model.addAttribute("time", refreshSchedule);
model.addAttribute("message", "文件正在转换中,请稍候...");
return WAITING_FILE_PREVIEW_PAGE;
} catch (Exception e) {
@@ -101,14 +100,33 @@ public class CadFilePreviewImpl implements FilePreview {
*/
private void startAsyncConversion(String filePath, String outFilePath,
String cacheName, FileAttribute fileAttribute) {
//获取cad转换路径
String cadConverterPath = ConfigConstants.getCadConverterPath();
int conversionModule= ConfigConstants.getConversionModule();
if(cadConverterPath.equals("false")){
//默认aspose-cad
conversionModule = 1;
}
CompletableFuture<Boolean> conversionFuture;
// 启动异步转换
CompletableFuture<Boolean> conversionFuture = cadtopdfservice.cadToPdfAsync(
filePath,
outFilePath,
cacheName,
ConfigConstants.getCadPreviewType(),
fileAttribute
);
if(conversionModule==2){
conversionFuture = cadtopdfservice.cadViewerConvert(
filePath,
outFilePath,
cadConverterPath,
ConfigConstants.getCadPreviewType(),
cacheName
);
}else {
conversionFuture = cadtopdfservice.cadToPdfAsync(
filePath,
outFilePath,
cacheName,
ConfigConstants.getCadPreviewType(),
fileAttribute
);
}
// 添加转换完成后的回调
conversionFuture.whenCompleteAsync((success, throwable) -> {
@@ -144,13 +162,18 @@ public class CadFilePreviewImpl implements FilePreview {
FileAttribute fileAttribute) {
cacheName = WebUtils.encodeFileName(cacheName);
String baseUrl = BaseUrlFilter.getBaseUrl();
int conversionModule= ConfigConstants.getConversionModule();
if ("tif".equalsIgnoreCase(cadPreviewType)) {
model.addAttribute("currentUrl", cacheName);
return TIFF_FILE_PREVIEW_PAGE;
} else if ("svg".equalsIgnoreCase(cadPreviewType)) {
model.addAttribute("currentUrl", cacheName);
return SVG_FILE_PREVIEW_PAGE;
if(conversionModule==2){
return CADVIEWER_FILE_PREVIEW_PAGE;
}else {
return SVG_FILE_PREVIEW_PAGE;
}
}
if (baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) ||

View File

@@ -22,10 +22,8 @@ public class CodeFilePreviewImpl implements FilePreview {
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
filePreviewHandle.filePreviewHandle(url, model, fileAttribute);
String suffix = fileAttribute.getSuffix();
if(suffix.equalsIgnoreCase("htm") || suffix.equalsIgnoreCase("html") || suffix.equalsIgnoreCase("shtml") ){
model.addAttribute("pdfUrl", url);
return TXT_FILE_PREVIEW_PAGE; //直接输出html
}
boolean isHtmlFile = suffix.equalsIgnoreCase("htm") || suffix.equalsIgnoreCase("html") || suffix.equalsIgnoreCase("shtml");
model.addAttribute("isHtmlFile", isHtmlFile);
return CODE_FILE_PREVIEW_PAGE;
}
}

View File

@@ -1,5 +1,6 @@
package cn.keking.service.impl;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse;
import cn.keking.service.FileHandlerService;
@@ -10,6 +11,7 @@ import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.List;
@@ -32,17 +34,26 @@ public class CommonPreviewImpl implements FilePreview {
@Override
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
// 不是http开头浏览器不能直接访问需下载到本地
boolean forceUpdatedCache = fileAttribute.forceUpdatedCache(); //是否启用强制更新命令
String fileName = fileAttribute.getName(); //获取原始文件名
if (forceUpdatedCache || !fileHandlerService.listConvertedFiles().containsKey(fileName) || !ConfigConstants.isCacheEnabled()) {
if (url != null && !url.toLowerCase().startsWith("http")) {
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, null);
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
if (response.isFailure()) {
return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
} else {
String file = fileHandlerService.getRelativePath(response.getContent());
model.addAttribute("currentUrl", file);
if (ConfigConstants.isCacheEnabled()) {
fileHandlerService.addConvertedFile(fileName, file);
}
}
} else {
model.addAttribute("currentUrl", url);
}
return null;
}
model.addAttribute("currentUrl", fileHandlerService.getConvertedFile(fileName));
return null;
}
}

View File

@@ -97,8 +97,10 @@ public class MediaFilePreviewImpl implements FilePreview {
try {
// 启动异步转换,并添加回调处理
startAsyncConversion(filePath, outFilePath, cacheName, fileAttribute);
int refreshSchedule = ConfigConstants.getTime();
// 返回等待页面
model.addAttribute("fileName", fileName);
model.addAttribute("time", refreshSchedule);
model.addAttribute("message", "视频文件正在转换中,请稍候...");
return WAITING_FILE_PREVIEW_PAGE;
} catch (Exception e) {

View File

@@ -0,0 +1,25 @@
package cn.keking.service.impl;
import cn.keking.model.FileAttribute;
import cn.keking.service.FilePreview;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
/**
* Dcm 文件处理
*/
@Service
public class MsgFilePreviewImpl implements FilePreview {
private final CommonPreviewImpl commonPreview;
public MsgFilePreviewImpl(CommonPreviewImpl commonPreview) {
this.commonPreview = commonPreview;
}
@Override
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
commonPreview.filePreviewHandle(url,model,fileAttribute);
return MSG_FILE_PREVIEW_PAGE;
}
}

View File

@@ -112,8 +112,10 @@ public class OfficeFilePreviewImpl implements FilePreview {
try {
// 启动异步转换
startAsyncOfficeConversion(filePath, outFilePath, cacheName, fileAttribute, officePreviewType);
int refreshSchedule = ConfigConstants.getTime();
// 返回等待页面
model.addAttribute("fileName", fileName);
model.addAttribute("time", refreshSchedule);
model.addAttribute("message", "文件正在转换中,请稍候...");
return WAITING_FILE_PREVIEW_PAGE;
} catch (Exception e) {
@@ -160,7 +162,7 @@ public class OfficeFilePreviewImpl implements FilePreview {
if (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) ||
OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType)) {
FileConvertStatusManager.updateProgress(cacheName, "正在转换PDF为图片", 90);
imageUrls = pdftojpgservice.pdf2jpg(outFilePath, outFilePath, cacheName, fileAttribute);
imageUrls = pdftojpgservice.pdf2jpg(outFilePath, outFilePath, fileAttribute);
}
// 缓存处理

View File

@@ -8,7 +8,6 @@ import cn.keking.service.FilePreview;
import cn.keking.service.PdfToJpgService;
import cn.keking.utils.DownloadUtils;
import cn.keking.utils.FileConvertStatusManager;
import cn.keking.utils.KkFileUtils;
import cn.keking.utils.WebUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.poi.EncryptedDocumentException;
@@ -37,16 +36,19 @@ public class PdfFilePreviewImpl implements FilePreview {
private final FileHandlerService fileHandlerService;
private final OtherFilePreviewImpl otherFilePreview;
private final PdfToJpgService pdftojpgservice;
private final OfficeFilePreviewImpl officefilepreviewimpl;
// 用于处理回调的线程池
private static final ExecutorService callbackExecutor = Executors.newFixedThreadPool(3);
public PdfFilePreviewImpl(FileHandlerService fileHandlerService,
OtherFilePreviewImpl otherFilePreview,
OfficeFilePreviewImpl officefilepreviewimpl,
PdfToJpgService pdftojpgservice) {
this.fileHandlerService = fileHandlerService;
this.otherFilePreview = otherFilePreview;
this.pdftojpgservice = pdftojpgservice;
this.officefilepreviewimpl = officefilepreviewimpl;
}
@Override
@@ -56,35 +58,25 @@ public class PdfFilePreviewImpl implements FilePreview {
boolean forceUpdatedCache = fileAttribute.forceUpdatedCache(); //是否启用强制更新命令
String outFilePath = fileAttribute.getOutFilePath(); //生成的文件路径
String originFilePath; //原始文件路径
String cacheName = fileAttribute.getCacheName();
String cacheName = pdfName+officePreviewType;
String filePassword = fileAttribute.getFilePassword(); // 获取密码
int refreshSchedule = ConfigConstants.getTime();
// 查询转换状态
FileConvertStatusManager.ConvertStatus status = FileConvertStatusManager.getConvertStatus(cacheName);
if (status != null) {
if (status.getStatus() == FileConvertStatusManager.Status.CONVERTING) {
// 正在转换中,返回等待页面
model.addAttribute("fileName", pdfName);
model.addAttribute("time", refreshSchedule);
model.addAttribute("message", status.getRealTimeMessage());
return WAITING_FILE_PREVIEW_PAGE;
} else if (status.getStatus() == FileConvertStatusManager.Status.TIMEOUT) {
// 超时状态,不允许重新转换
return otherFilePreview.notSupportedFile(model, fileAttribute, "文件转换已超时,无法继续转换");
}
String statusResult = officefilepreviewimpl.checkAndHandleConvertStatus(model, pdfName, cacheName, fileAttribute);
if (statusResult != null) {
return statusResult;
}
boolean jiami=false;
if(!ObjectUtils.isEmpty(filePassword)){
jiami=pdftojpgservice.hasEncryptedPdfCacheSimple(outFilePath);
}
if (OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) ||
OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType)) {
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
if (forceUpdatedCache || !fileHandlerService.listConvertedFiles().containsKey(cacheName) || !ConfigConstants.isCacheEnabled()) {
if(jiami){
return renderPreview(model, cacheName, outFilePath,
officePreviewType, pdfName, fileAttribute);
officePreviewType, fileAttribute);
}
// 当文件不存在时,就去下载
ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, pdfName);
@@ -98,15 +90,17 @@ public class PdfFilePreviewImpl implements FilePreview {
if (checkIfPdfNeedsPassword(originFilePath, cacheName, pdfName)) {
model.addAttribute("needFilePassword", true);
model.addAttribute("fileName", pdfName);
model.addAttribute("cacheName", cacheName);
model.addAttribute("cacheName", pdfName);
return EXEL_FILE_PREVIEW_PAGE;
}
}
try {
// 启动异步转换
startAsyncPdfConversion(originFilePath, outFilePath, cacheName, pdfName, fileAttribute);
int refreshSchedule = ConfigConstants.getTime();
// 返回等待页面
model.addAttribute("fileName", pdfName);
model.addAttribute("time", refreshSchedule);
model.addAttribute("message", "文件正在转换中,请稍候...");
return WAITING_FILE_PREVIEW_PAGE;
} catch (Exception e) {
@@ -116,7 +110,7 @@ public class PdfFilePreviewImpl implements FilePreview {
} else {
// 如果已有缓存,直接渲染预览
return renderPreview(model, cacheName, outFilePath,
officePreviewType, pdfName, fileAttribute);
officePreviewType, fileAttribute);
}
} else {
// 处理普通PDF预览非图片转换
@@ -175,13 +169,13 @@ public class PdfFilePreviewImpl implements FilePreview {
FileConvertStatusManager.updateProgress(cacheName, "正在启动PDF转换", 10);
List<String> imageUrls = pdftojpgservice.pdf2jpg(originFilePath, outFilePath,
pdfName, fileAttribute);
fileAttribute);
if (imageUrls != null && !imageUrls.isEmpty()) {
boolean usePasswordCache = fileAttribute.getUsePasswordCache();
String filePassword = fileAttribute.getFilePassword();
if (ConfigConstants.isCacheEnabled() && (ObjectUtils.isEmpty(filePassword) || usePasswordCache)) {
fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
fileHandlerService.addConvertedFile(cacheName, fileHandlerService.getRelativePath(outFilePath));
}
FileConvertStatusManager.updateProgress(cacheName, "转换完成", 100);
// 短暂延迟后清理状态
@@ -214,17 +208,7 @@ public class PdfFilePreviewImpl implements FilePreview {
// 添加转换完成后的回调
conversionFuture.whenCompleteAsync((imageUrls, throwable) -> {
if (imageUrls != null && !imageUrls.isEmpty()) {
try {
// 是否保留PDF源文件只在转换成功后才删除
if (!fileAttribute.isCompressFile() && ConfigConstants.getDeleteSourceFile()) {
KkFileUtils.deleteFileByPath(originFilePath);
}
} catch (Exception e) {
logger.error("PDF转换后续处理失败: {}", originFilePath, e);
}
} else {
// 转换失败,保留源文件供排查问题
if (imageUrls == null || imageUrls.isEmpty()) {
logger.error("PDF转换失败保留源文件: {}", originFilePath);
if (throwable != null) {
logger.error("转换失败原因: ", throwable);
@@ -238,7 +222,7 @@ public class PdfFilePreviewImpl implements FilePreview {
*/
private String renderPreview(Model model, String cacheName,
String outFilePath, String officePreviewType,
String pdfName, FileAttribute fileAttribute) {
FileAttribute fileAttribute) {
try {
List<String> imageUrls;
if(pdftojpgservice.hasEncryptedPdfCacheSimple(outFilePath)){
@@ -251,7 +235,7 @@ public class PdfFilePreviewImpl implements FilePreview {
}
model.addAttribute("imgUrls", imageUrls);
model.addAttribute("currentUrl", imageUrls.get(0));
model.addAttribute("currentUrl", imageUrls.getFirst());
if (OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType)) {
return OFFICE_PICTURE_FILE_PREVIEW_PAGE;

View File

@@ -27,16 +27,28 @@ public class PictureFilePreviewImpl extends CommonPreviewImpl {
@Override
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
url= KkFileUtils.htmlEscape(url);
String suffix = fileAttribute.getSuffix();
List<String> imgUrls = new ArrayList<>();
imgUrls.add(url);
String compressFileKey = fileAttribute.getCompressFileKey();
List<String> zipImgUrls = fileHandlerService.getImgCache(compressFileKey);
if (!CollectionUtils.isEmpty(zipImgUrls)) {
imgUrls.addAll(zipImgUrls);
model.addAttribute("imgUrls", imgUrls);
}else {
// 不是http开头浏览器不能直接访问需下载到本地
super.filePreviewHandle(url, model, fileAttribute);
if ( url.toLowerCase().startsWith("file") || url.toLowerCase().startsWith("ftp")) {
model.addAttribute("imgUrls", fileAttribute.getName());
}else {
model.addAttribute("imgUrls", url);
}
}
if(suffix.equalsIgnoreCase("heic")){
return HEIC_FILE_PREVIEW_PAGE;
}else {
return PICTURE_FILE_PREVIEW_PAGE;
}
// 不是http开头浏览器不能直接访问需下载到本地
super.filePreviewHandle(url, model, fileAttribute);
model.addAttribute("imgUrls", imgUrls);
return PICTURE_FILE_PREVIEW_PAGE;
}
}

View File

@@ -70,8 +70,10 @@ public class TiffFilePreviewImpl implements FilePreview {
try {
// 启动异步转换
startAsyncTiffConversion(filePath, outFilePath, cacheName, fileName, fileAttribute, tifPreviewType, forceUpdatedCache);
int refreshSchedule = ConfigConstants.getTime();
// 返回等待页面
model.addAttribute("fileName", fileName);
model.addAttribute("time", refreshSchedule);
model.addAttribute("message", "文件正在转换中,请稍候...");
return WAITING_FILE_PREVIEW_PAGE;
} catch (Exception e) {