Browse Source

新增pdf 预览功能

ai_300_new
zhouhaibin 1 month ago
parent
commit
294ad4dd80
  1. 4
      ruoyi-admin/src/main/resources/application-dev.yml
  2. 2
      ruoyi-admin/src/main/resources/application.yml
  3. 12
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/DocumentTaskResultsController.java
  4. 2
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/DocumentTasks.java
  5. 2
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/DocumentTasksBo.java
  6. 3
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/BaseTaskVo.java
  7. 2
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/DocumentTasksVo.java
  8. 8
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IDocumentTaskResultsService.java
  9. 131
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/DocumentTaskResultsServiceImpl.java

4
ruoyi-admin/src/main/resources/application-dev.yml

@ -52,8 +52,8 @@ spring:
# url: jdbc:mysql://localhost:3306/zaojia?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username: root
# password: root
# url: jdbc:mysql://10.1.21.250:3306/aitable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://218.0.1.42:53306/aitable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://10.1.21.250:3306/aitable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# url: jdbc:mysql://218.0.1.42:53306/aitable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 'HXj-6nR|D8xy*h#!I&:('
# 从库数据源

2
ruoyi-admin/src/main/resources/application.yml

@ -71,7 +71,7 @@ spring:
basename: i18n/messages
profiles:
#@profiles.active@
active: dev
active: test
# 文件上传
servlet:
multipart:

12
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/DocumentTaskResultsController.java

@ -156,4 +156,16 @@ public class DocumentTaskResultsController extends BaseController {
@PathVariable Long[] ids,HttpServletResponse response) {
documentTaskResultsService.downloadResult(ids,response);
}
/**
* 获取PDF文件流
*
* @param taskId 任务ID
*/
@GetMapping("/getPdfStream/{taskId}")
public void getPdfStream(@NotNull(message = "任务ID不能为空")
@PathVariable String taskId,
HttpServletResponse response) {
documentTaskResultsService.getPdfStream(taskId, response);
}
}

2
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/DocumentTasks.java

@ -80,4 +80,6 @@ public class DocumentTasks extends TenantEntity {
*/
private String taskIndustry;
private String pdfPath;
}

2
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/DocumentTasksBo.java

@ -30,7 +30,7 @@ public class DocumentTasksBo extends BaseTaskBo {
*/
private String id;
private String pdfPath;

3
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/BaseTaskVo.java

@ -61,7 +61,7 @@ public class BaseTaskVo {
@ExcelProperty(value = "上传时间")
private Date createTime;
private Long ossId;
/**
* 创建者
*/
@ -70,4 +70,5 @@ public class BaseTaskVo {
@ExcelProperty(value = "更新时间")
private Date updateTime;
}

2
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/DocumentTasksVo.java

@ -31,6 +31,6 @@ public class DocumentTasksVo extends BaseTaskVo implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty(value = "主键")
private String id;
private String pdfPath;
}

8
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IDocumentTaskResultsService.java

@ -95,4 +95,12 @@ public interface IDocumentTaskResultsService {
Boolean updateResultItemStatus(String id, String field, String value);
void downloadResult(Long[] ids, HttpServletResponse response);
/**
* 获取PDF文件流
*
* @param taskId 任务ID
* @param response HTTP响应对象
*/
void getPdfStream(String taskId, HttpServletResponse response);
}

131
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/DocumentTaskResultsServiceImpl.java

@ -10,6 +10,7 @@ import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataSet;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.MapstructUtils;
@ -22,14 +23,20 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.productManagement.domain.DocumentTaskResultDetail;
import org.dromara.productManagement.domain.DocumentTasks;
import org.dromara.productManagement.domain.bo.DocumentTasksBo;
import org.dromara.productManagement.domain.vo.DocumentTaskResultVO;
import org.dromara.productManagement.domain.vo.DocumentTasksVo;
import org.dromara.productManagement.enums.TaskEnum;
import org.dromara.productManagement.mapper.DocumentTaskResultDetailMapper;
import org.dromara.productManagement.mapper.DocumentTasksMapper;
import org.dromara.productManagement.service.IDocumentTasksService;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Safelist;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.productManagement.domain.bo.DocumentTaskResultsBo;
import org.dromara.productManagement.domain.vo.DocumentTaskResultsVo;
@ -37,17 +44,23 @@ import org.dromara.productManagement.domain.DocumentTaskResults;
import org.dromara.productManagement.mapper.DocumentTaskResultsMapper;
import org.dromara.productManagement.service.IDocumentTaskResultsService;
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.springframework.beans.factory.annotation.Value;
import javax.sql.DataSource;
import javax.xml.parsers.SAXParser;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.nio.file.Files;
/**
* 文档任务结果Service业务层处理
@ -57,12 +70,21 @@ import java.util.zip.ZipOutputStream;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class DocumentTaskResultsServiceImpl implements IDocumentTaskResultsService {
private final DocumentTaskResultsMapper baseMapper;
private final DocumentTaskResultDetailMapper documentTaskResultDetailMapper;
private final IDocumentTasksService documentTasksService;
private final DocumentTasksMapper documentTasksMapper;
private final DictService dictTypeService;
protected final ISysOssService ossService;
@Value("${chat.tempfilePath}")
protected String tempfilePath;
@Value("${chat.filePath}")
protected String fileRootPath;
@Autowired
private DataSource dataSource;
/**
* 查询文档任务结果
@ -243,22 +265,22 @@ public class DocumentTaskResultsServiceImpl implements IDocumentTaskResultsServi
if (!"isRead".equals(field) && !"isAdopted".equals(field)) {
throw new RuntimeException("不支持更新的字段: " + field);
}
// 验证值是否合法
if (!"0".equals(value) && !"1".equals(value)) {
throw new RuntimeException("无效的值: " + value);
}
try {
LambdaUpdateWrapper<DocumentTaskResultDetail> updateWrapper = Wrappers.lambdaUpdate(DocumentTaskResultDetail.class);
updateWrapper.eq(DocumentTaskResultDetail::getId, id);
if ("isRead".equals(field)) {
updateWrapper.set(DocumentTaskResultDetail::getIsRead, value);
} else {
updateWrapper.set(DocumentTaskResultDetail::getIsAdopted, value);
}
return documentTaskResultDetailMapper.update(null, updateWrapper) > 0;
} catch (Exception e) {
throw new RuntimeException("更新状态失败: " + e.getMessage(), e);
@ -282,7 +304,6 @@ public class DocumentTaskResultsServiceImpl implements IDocumentTaskResultsServi
DocumentTasksVo documentTasksVo = documentTasksService.queryById(list.get(0).getDocumentTaskId());
String documentName = documentTasksVo.getDocumentName();
String tempDir = System.getProperty("java.io.tmpdir");
String zipFileName = "results_" +documentName + ".zip";
String zipFilePath = tempDir + File.separator + zipFileName;
@ -520,4 +541,104 @@ public class DocumentTaskResultsServiceImpl implements IDocumentTaskResultsServi
content = content.replaceAll("style=\"\"", "");
return content.trim();
}
@Override
public void getPdfStream(String taskId, HttpServletResponse response) {
try {
// 查询任务信息
DocumentTasksVo task = documentTasksService.queryById(Long.valueOf(taskId));
String outputPath = tempfilePath + File.separator + "pdf_preview" + File.separator;
String filerotPath ="";
if (task == null) {
throw new RuntimeException("任务不存在");
}
String pdfPath = task.getPdfPath();
String filePath="";
if (StringUtils.isNotEmpty(pdfPath)) {
// 如果pdfPath存在,直接使用该路径
filePath = pdfPath;
} else {
// 如果pdfPath不存在,从oss获取文件
Long ossId = task.getOssId();
if (ossId == null) {
throw new RuntimeException("文件不存在");
}
SysOssVo fileInfo = ossService.getById(ossId);
if (fileInfo == null) {
throw new RuntimeException("文件信息不存在");
}
String fileName = fileInfo.getOriginalName();
// 创建pdf预览目录
File previewDir = new File(outputPath);
if (!previewDir.exists()) {
previewDir.mkdirs();
}
filerotPath = fileRootPath + fileInfo.getFileName();
// 如果不是pdf文件,需要转换
if (!fileName.toLowerCase().endsWith(".pdf")) {
// 更新文件路径为转换后的pdf路径
String originalFileName = fileInfo.getFileName();
// 获取不带路径的文件名
String fileNameOnly = originalFileName.substring(originalFileName.lastIndexOf("/") + 1);
// 获取不带扩展名的文件名
String fileNameWithoutExt = fileNameOnly.substring(0, fileNameOnly.lastIndexOf("."));
filePath = outputPath + fileNameWithoutExt + ".pdf";
log.info("开始转换文件: " + fileName + " -> " + filePath);
}
}
log.info("开始输出文件: " + filePath);
// 读取文件并输出到response
File file = new File(filePath);
if (!file.exists()) {
log.info("开始转换文件: 文件不存在" + filePath);
// 使用libreoffice转换为pdf
ProcessBuilder builder = new ProcessBuilder("libreoffice", "--headless", "--convert-to", "pdf", filerotPath, "--outdir", outputPath);
Process process = builder.start();
int completed = process.waitFor();
if (completed != 0) {
InputStream errorStream = process.getErrorStream();
String errorMessage = new String(errorStream.readAllBytes());
process.destroyForcibly();
throw new RuntimeException("文件转换失败: " + errorMessage);
}
process.destroyForcibly();
}
log.info("开始输出文件: 文件存在" + filePath);
// 使用JDBC更新数据库
try (Connection conn = dataSource.getConnection()) {
String sql = "UPDATE document_tasks SET pdf_path = ? WHERE id = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, filePath);
pstmt.setLong(2, Long.parseLong(taskId));
pstmt.executeUpdate();
}
} catch (SQLException e) {
log.error("更新PDF路径失败", e);
throw new RuntimeException("更新PDF路径失败: " + e.getMessage());
}
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getName(), StandardCharsets.UTF_8.name()));
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis, 8192);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.flush();
}
} catch (Exception e) {
throw new RuntimeException("获取PDF文件流失败: " + e.getMessage());
}
}
}

Loading…
Cancel
Save