package cn.cslg.pas.service;
import cn.cslg.pas.common.CyCacheUtil;
import cn.cslg.pas.common.core.base.Constants;
import cn.cslg.pas.common.model.dto.PatentDTO;
import cn.cslg.pas.common.model.dto.UploadFileDTO;
import cn.cslg.pas.common.model.vo.PatentInstructionVO;
import cn.cslg.pas.common.model.vo.PatentVO;
import cn.cslg.pas.common.model.vo.SystemFile;
import cn.cslg.pas.common.utils.*;
import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.pas.domain.Patent;
import cn.cslg.pas.domain.PatentInstruction;
import cn.cslg.pas.domain.Task;
import cn.cslg.pas.mapper.PatentInstructionMapper;
import cn.cslg.pas.mapper.PatentMapper;
import cn.cslg.pas.service.upLoadPatent.MessageService;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.multipdf.Splitter;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* 专利说明书 服务类
*
*
* @author 王岩
* @since 2022-03-02
*/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class PatentInstructionService extends ServiceImpl {
private final PatentService patentService;
private final PatentMapper patentMapper;
private final TaskService taskService;
private final MessageService messageService;
private final FileManagerService fileManagerService;
private final CacheManager cacheManager;
private final CyCacheUtil cyCacheUtil;
private final FileUtils fileUtils;
private final LoginUtils loginUtils;
public IPage getPageList(PatentInstructionVO params) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotEmpty(params.getPatentNo())) {
queryWrapper.like(PatentInstruction::getPatentNo, params.getPatentNo());
}
if (params.getType() != null) {
queryWrapper.eq(PatentInstruction::getType, params.getType());
}
if (params.getPatentId() != null) {
queryWrapper.eq(PatentInstruction::getPatentId, params.getPatentId());
}
IPage pageList = this.page(new Page<>(params.getCurrent(), params.getSize()), queryWrapper);
return pageList;
}
public List getPatentInstructionByPatentNo(String patentNo) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PatentInstruction::getPatentNo, patentNo);
return this.list(queryWrapper);
}
public List getPatentInstructionByPatentNo(List patentNo) {
if (patentNo == null || patentNo.size() == 0) {
return new ArrayList<>();
}
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(PatentInstruction::getPatentNo, patentNo);
return this.list(queryWrapper);
}
public PatentInstruction getPatentInstructionByPatentNoAndType(String patentNo, Integer type) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PatentInstruction::getType, type);
queryWrapper.eq(PatentInstruction::getPatentNo, patentNo).last("Limit 1");
return this.getOne(queryWrapper);
}
@Async("singleThreadAsyncTaskExecutor")
@Transactional(rollbackFor = Exception.class)
public void batchUpload(String url, Integer type, String remark, Integer userId) {
String tempPath = null;
try {
String tempDirectoryName = IdUtil.simpleUUID();
tempPath = fileUtils.getSystemPath(tempDirectoryName);
File tempDirectory = new File(tempPath);
if (!tempDirectory.exists()) {
tempDirectory.mkdir();
}
ZipUtil.unzip(fileUtils.getSystemPath(url), tempPath);
List fileList = FileUtil.loopFiles(tempPath).stream().filter(item -> FileUtil.getType(item).equals("pdf")).collect(Collectors.toList());
for (int i = 0; i < fileList.size(); i++) {
File file = fileList.get(i);
String fileName = file.getName();
String patentNo = FileUtil.getPrefix(file);
String saveName = IdUtil.simpleUUID() + ".pdf";
String saveUrl = fileUtils.getDirectory(saveName);
String savePath = fileUtils.getSystemPath(saveUrl);
FileUtil.copy(file.getPath(), savePath, true);
PatentInstruction temp = this.getPatentInstructionByPatentNoAndType(patentNo, type);
if (temp == null) {
temp = new PatentInstruction();
} else {
FileUtil.del(fileUtils.getSystemPath(temp.getUrl()));
}
temp.setPatentNo(patentNo);
temp.setFileName(saveName);
temp.setSize(FileUtil.size(file));
temp.setUrl(saveUrl);
temp.setRemark(remark);
temp.setCreateBy(userId);
temp.setType(type);
temp.insertOrUpdate();
Map data = new HashMap<>();
data.put("index", i);
data.put("total", fileList.size());
WebSocketServer.sendInfo(Response.websocket(data, ResponseEnum.BATCH_UPLOAD_INSTRUCTION_TASK_SUCCESS), String.valueOf(userId));
}
} catch (Exception e) {
e.printStackTrace();
WebSocketServer.sendInfo(Response.error(ResponseEnum.BATCH_UPLOAD_INSTRUCTION_TASK_ERROR), String.valueOf(userId));
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
} finally {
FileUtil.del(tempPath);
}
}
public String add(MultipartFile file, PatentInstruction patentInstruction) {
UploadFileDTO fileDTO = fileUtils.uploadFile(file);
patentInstruction.setCreateBy(loginUtils.getId());
patentInstruction.setUrl(fileDTO.getPath());
patentInstruction.setFileName(fileDTO.getFileName());
patentInstruction.insert();
return Response.success(patentInstruction.getId());
}
@Transactional
public String edit(MultipartFile file, PatentInstruction patentInstruction) {
this.deleteByPatentNoAndType(patentInstruction.getPatentNo(), patentInstruction.getType());
if (StringUtils.isNotEmpty(patentInstruction.getUrl())) {
FileUtil.del(fileUtils.getSystemPath(patentInstruction.getUrl()));
}
UploadFileDTO fileDTO = fileUtils.uploadFile(file);
patentInstruction.setCreateBy(loginUtils.getId());
patentInstruction.setUrl(fileDTO.getPath());
patentInstruction.setFileName(fileDTO.getFileName());
patentInstruction.setSize(fileDTO.getFileSize());
patentInstruction.insert();
return Response.success(true);
}
/**
* 说明书pdf数据入库
*
* @param patentNo 专利号
* @param pdf 装载pdf数据对象
*/
@Transactional
public String edit(String patentNo, UploadFileDTO pdf) {
//先把实体类对象赋好值
PatentInstruction patentInstruction = new PatentInstruction();
patentInstruction.setUrl(pdf.getPath());
patentInstruction.setFileName(pdf.getFileName());
patentInstruction.setSize(pdf.getFileSize());
patentInstruction.setPatentNo(patentNo);
patentInstruction.setType(1);
//根据专利号和pdf类型(1公开 2授权)查询该专利号是否已有公开的pdf
List patentInstructions = this.list(new LambdaQueryWrapper().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 1));
if (patentInstructions != null && patentInstructions.size() > 0) { //若有则更新
patentInstruction.setId(patentInstructions.get(0).getId());
this.updateById(patentInstruction);
} else { //若没有则新增
this.save(patentInstruction);
}
return Response.success(true);
}
@Transactional
public String edit2(String patentNo, UploadFileDTO pdf2) {
//先把实体类对象赋好值
PatentInstruction patentInstruction = new PatentInstruction();
patentInstruction.setUrl(pdf2.getPath());
patentInstruction.setFileName(pdf2.getFileName());
patentInstruction.setSize(pdf2.getFileSize());
patentInstruction.setPatentNo(patentNo);
patentInstruction.setType(2);
//根据专利号和pdf类型(1公开 2授权)查询该专利号是否已有授权的pdf
List patentInstructions = this.list(new LambdaQueryWrapper().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 2));
//若有则更新
if (patentInstructions != null && patentInstructions.size() > 0) {
patentInstruction.setId(patentInstructions.get(0).getId());
this.updateById(patentInstruction);
} else { //若没有则新增
this.save(patentInstruction);
}
return Response.success(true);
}
@Transactional
public String edit12(String patentNo, UploadFileDTO pdf1, UploadFileDTO pdf2) {
//处理公开pdf文档(更新或新增)
PatentInstruction patentInstruction1 = new PatentInstruction();
patentInstruction1.setUrl(pdf1.getPath());
patentInstruction1.setFileName(pdf1.getFileName());
patentInstruction1.setSize(pdf1.getFileSize());
patentInstruction1.setPatentNo(patentNo);
patentInstruction1.setType(1);
//先查询库中是否已有该专利号的公开pdf文档
List patentInstructions1 = this.list(new LambdaQueryWrapper().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 1));
//若有则更新
if (patentInstructions1 != null && patentInstructions1.size() > 0) {
patentInstruction1.setId(patentInstructions1.get(0).getId());
this.updateById(patentInstruction1);
} else { //若没有则新增
this.save(patentInstruction1);
}
//处理授权pdf文档(更新或新增)
PatentInstruction patentInstruction2 = new PatentInstruction();
patentInstruction2.setUrl(pdf2.getPath());
patentInstruction2.setFileName(pdf2.getFileName());
patentInstruction2.setSize(pdf2.getFileSize());
patentInstruction2.setPatentNo(patentNo);
patentInstruction2.setType(2);
//再查询库中是否已有该专利号的授权pdf文档
List patentInstructions2 = this.list(new LambdaQueryWrapper().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 2));
//若有则更新
if (patentInstructions2 != null && patentInstructions2.size() > 0) {
patentInstruction2.setId(patentInstructions2.get(0).getId());
this.updateById(patentInstruction2);
} else { //若没有则新增
this.save(patentInstruction2);
}
return Response.success(true);
}
public String delete(Integer id) {
PatentInstruction temp = this.getById(id);
this.removeById(id);
if (StringUtils.isNotEmpty(temp.getUrl())) {
FileUtil.del(fileUtils.getSystemPath(temp.getUrl()));
}
return Response.success(true);
}
public void deleteByPatentNoAndType(String patentNo, Integer type) {
this.remove(Wrappers.lambdaQuery().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, type));
}
public void importPatentInstruction(Integer userId, String tempPath, String patentIdPatentNoJson, String patentInstructionJson) {
List importPatentList = JsonUtils.jsonToList(patentIdPatentNoJson, Patent.class);
List importPatentInstructionList = JsonUtils.jsonToList(patentInstructionJson, PatentInstruction.class);
List localPatentInstructionList = this.getPatentInstructionByPatentNo(importPatentList.stream().map(Patent::getPatentNo).collect(Collectors.toList()));
for (PatentInstruction patentInstruction : importPatentInstructionList) {
String fileName = IdUtil.simpleUUID() + "." + FileUtil.extName(patentInstruction.getFileName());
String saveUrl = fileUtils.getDirectory(fileName);
String savePath = fileUtils.getSystemPath(saveUrl);
String tempInstruction = tempPath + FileUtils.FILE_SEPARATOR + Constants.PATENT_INSTRUCTION_DIRECTORY_NAME + FileUtils.FILE_SEPARATOR + patentInstruction.getFileName();
patentInstruction.setId(null);
patentInstruction.setFileName(fileName);
patentInstruction.setUrl(saveUrl);
patentInstruction.setCreateBy(userId);
patentInstruction.setCreateTime(new Date());
if (FileUtil.exist(tempInstruction)) {
patentInstruction.insert();
FileUtil.copy(tempInstruction, savePath, true);
}
}
localPatentInstructionList.forEach(item -> {
item.deleteById();
FileUtil.del(fileUtils.getSystemPath(item.getUrl()));
});
}
/**
* 合并导出专题库专利的pdf首页文件
*
* @param params 查询条件
*/
public void exportPatentPdfFirstPages(PatentVO params) throws IOException {
log.info("开始处理【合并导出专题库专利的pdf首页文件】的业务,业务参数为:{}", params);
//根据筛选条件分页查询专利清单(本次查询目的只是获得专利总数和总页数)
IPage pageList0 = patentMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params);
if (pageList0 == null || pageList0.getRecords() == null || pageList0.getRecords().size() == 0) {
ThrowException.throwXiaoShiException("合并专利pdf首页文档失败,未查询到任何专利信息!");
}
int total = (int) pageList0.getTotal(); //专利总数(作为任务进度总数)
long pages = pageList0.getPages(); //总页数(用来计算要检索几次)
ArrayList filePaths = new ArrayList<>(); //存放所有临时文件(说明书pdf首页的文件)路径
String mergedFilePath = StringUtils.getUUID() + ".pdf"; //合并后的pdf文件路径
PDFMergerUtility pdfMerger = new PDFMergerUtility(); //pdf合并工具
//上传任务
Task task = new Task()
.setFileName(mergedFilePath)
.setProjectId(params.getProjectId())
.setType(6)
.setCreateBy(loginUtils.getId())
.setStartTime(DateUtils.getDateTime())
.setTotal(total)
.setStatus(6)
.setDefaultNum(0)
.setSuccessNum(0)
.setTrueSuccessNum(0);
taskService.save(task);
//一页一页检索
for (long i = 1; i <= pages; i++) {
params.setCurrent(i);
IPage pageList = patentMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params);
List patents = pageList.getRecords(); //取出专利清单
List patentNos = patents.stream().map(Patent::getPatentNo).collect(Collectors.toList()); //过滤取出专利号
//根据专利号patentNos查询出所有pdf文档数据
List patentInstructions = this.list(new LambdaQueryWrapper().in(PatentInstruction::getPatentNo, patentNos));
//遍历当前专利号清单
for (String patentNo : patentNos) {
List patentInstructionList = patentInstructions.stream().filter(item -> item.getPatentNo().equals(patentNo)).collect(Collectors.toList());
//若有说明书pdf数据
PatentInstruction patentInstruction = new PatentInstruction();
if (patentInstructionList.size() > 1) { //若有多个,则过滤取出授权文档
patentInstruction = patentInstructionList.stream().filter(item -> item.getType() == 2).collect(Collectors.toList()).get(0);
} else if (patentInstructionList.size() == 1) { //若只有一个pdf,则直接取出
patentInstruction = patentInstructionList.get(0);
}
String filePath = fileUtils.getSystemPath() + patentInstruction.getUrl();
File pdfFile = new File(filePath);
//若没有说明书pdf数据,则手写空白页显示该专利没有说明书pdf
if (patentInstructionList.size() == 0 || !pdfFile.exists()) {
//创建文件,设置页码
PDDocument doc = new PDDocument();
PDPage pageOne = new PDPage(PDRectangle.A4);
doc.addPage(pageOne);
//创建页面内容流
PDPageContentStream contents = new PDPageContentStream(doc, pageOne, true, true, true);
//设置要使用的字体类型
//PDFont font = PDType1Font.COURIER_BOLD_OBLIQUE;
PDFont font = PDType1Font.HELVETICA;
//要写入的文本内容
String message = "no pdf of " + patentNo;
//设置字体大小
float fontSize = 36.0f;
PDRectangle pageSize = pageOne.getMediaBox();
float stringWidth = font.getStringWidth(message) * fontSize / 1000f;
//计算页中心位置
int rotation = pageOne.getRotation();
boolean rotate = rotation == 90 || rotation == 270;
float pageWidth = rotate ? pageSize.getHeight() : pageSize.getWidth();
float pageHeight = rotate ? pageSize.getWidth() : pageSize.getHeight();
double centeredXPosition = rotate ? pageHeight / 2f : (pageWidth - stringWidth) / 2f;
double centeredYPosition = rotate ? (pageWidth - stringWidth) / 2f : pageHeight / 2f;
contents.beginText();
//设置字体和大小
contents.setFont(font, fontSize);
//设置文本颜色
contents.setNonStrokingColor(Color.BLACK);
if (rotate) {
// rotate the text according to the page rotation
contents.setTextRotation(Math.PI / 2, centeredXPosition, centeredYPosition);
} else {
contents.setTextTranslation(centeredXPosition, centeredYPosition);
}
//开始写出文本内容
contents.showText(message);
contents.endText();
//记得关闭流对象要不然是无法成功保存pdf文档的
contents.close();
//创建临时文件 newFilePath
String newFilePath = StringUtils.getUUID() + ".pdf";
//将pdf首页写入临时文件
doc.save(newFilePath);
filePaths.add(newFilePath);
pdfMerger.addSource(newFilePath);
doc.close();
} else {
PDDocument doc = PDDocument.load(pdfFile);
Splitter splitter = new Splitter();
splitter.setStartPage(1);
splitter.setEndPage(1);
PDDocument needDoc = splitter.split(doc).get(0);
String newFilePath = StringUtils.getUUID() + ".pdf";
needDoc.save(newFilePath);
filePaths.add(newFilePath);
pdfMerger.addSource(newFilePath);
needDoc.close();
doc.close();
}
//更新任务表(完成数量+1)并发送进度
task.setSuccessNum(task.getSuccessNum() + 1);
task.setTrueSuccessNum(task.getTrueSuccessNum() + 1);
sendMessage(total, task);
}
}
// 设置合并生成pdf文件的名称
pdfMerger.setDestinationFileName(mergedFilePath);
// 合并PDF
pdfMerger.mergeDocuments();
//若最终合并成的pdf文件不存在
if (!new File(mergedFilePath).exists()) {
ThrowException.throwXiaoShiException("当前批次所有专利的说明书文档不存在或已丢失");
}
//File文件转成MultipartFile,上传文件至服务器,获得文件信息,更新任务表数据
MultipartFile multipartFile = FileToMultipartFileUtiles.fileToMultipartFile(mergedFilePath);
ArrayList multipartFiles = new ArrayList<>();
multipartFiles.add(multipartFile);
String res = fileManagerService.uploadFile(multipartFiles);
JSONObject jsonObject = JSONObject.parseObject(res);
List fileIds = JSONArray.parseArray(jsonObject.get("data").toString(), Integer.class);
res = fileManagerService.getSystemFileFromFMS(fileIds);
List systemFiles = JSONArray.parseArray(res, SystemFile.class);
SystemFile systemFile = systemFiles.get(0);
Task updateTask = new Task();
updateTask.setId(task.getId());
updateTask.setSystemFileId(fileIds.get(0));
updateTask.setUrl(systemFile.getFilePath().substring(systemFile.getFilePath().indexOf("file") + 4));
updateTask.setFileSize(Long.valueOf(systemFile.getFileLength()));
taskService.updateById(updateTask);
//最后要记得删除所有PDF首页临时文件
for (String filePath : filePaths) { //删除每个pdf首页文件
new File(filePath).delete();
}
//删除最终合并的pdf首页文件
new File(mergedFilePath).delete();
}
/**
* 更新任务表(完成数量+1)、发送websocket进度
*
* @param total 任务专利总数量
* @param task 任务对象
*/
private void sendMessage(int total, Task task) {
//更新任务表(完成数量+1),并发送进度+1
Task updateTask = new Task();
updateTask.setId(task.getId());
updateTask.setSuccessNum(task.getSuccessNum());
updateTask.setTrueSuccessNum(task.getTrueSuccessNum());
taskService.updateById(updateTask);
long percentage = (long) Math.floor((task.getSuccessNum() + 0D) / total * 100D);
//当全部完成时
if (task.getSuccessNum().equals(total)) {
percentage = 100L;
//任务表更新最终数据
task.setStatus(2);
updateTask.setStatus(task.getStatus());
updateTask.setEndTime(DateUtils.getDateTime());
taskService.updateById(updateTask);
}
//websocket发送进度
messageService.sendWebsocketMessage(task, total, task.getSuccessNum(), percentage);
}
/**
* pdf转图片方法Demo
*
* @param inputFile
* @param outputFile
*/
public void generateBookIamge(File inputFile, File outputFile) {
try {
PDDocument doc = PDDocument.load(inputFile);
PDFRenderer pdfRenderer = new PDFRenderer(doc);
// 提取的页码
int pageNumber = 0;
// 以300 dpi 读取存入 BufferedImage 对象
int dpi = 300;
RenderedImage buffImage = pdfRenderer.renderImageWithDPI(pageNumber, dpi, ImageType.RGB);
// 将 BufferedImage 写入到 png
ImageIO.write(buffImage, "png", outputFile);
// 关闭文档
doc.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 查询专题库专利的pdf首页清单
*
* @param params 查询条件
*/
public IPage queryPatentPdfFirstPages(PatentVO params) throws IOException {
log.info("开始处理【查询专题库专利的pdf首页图片清单】的业务,业务参数为:{}", params);
IPage pageListResult = new Page<>();
ArrayList patentDTOs = new ArrayList<>();
//根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
IPage pageList = patentMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params);
if (pageList == null || pageList.getRecords() == null || pageList.getRecords().size() == 0) {
ThrowException.throwXiaoShiException("查询专题库专利的pdf首页图片清单失败,未获取到任何专利信息!");
}
List patents = pageList.getRecords(); //取出专利清单
List patentNos = patents.stream().map(Patent::getPatentNo).collect(Collectors.toList()); //取出专利号
//查询出所有pdf文档数据
List patentInstructions = this.list(new LambdaQueryWrapper().in(PatentInstruction::getPatentNo, patentNos));
//遍历专利,装载数据
for (Patent patent : patents) {
PatentDTO patentDTO = new PatentDTO();
String patentNo = patent.getPatentNo();
List patentInstructionList = patentInstructions.stream().filter(patentInstruction -> patentInstruction.getPatentNo().equals(patentNo)).collect(Collectors.toList());
PatentInstruction patentInstruction = new PatentInstruction();
if (patentInstructionList.size() > 1) { //若有两个及以上pdf,则取授权文档
patentInstruction = patentInstructionList.stream().filter(item -> item.getType().equals(2)).collect(Collectors.toList()).get(0);
} else if (patentInstructionList.size() == 1) { //若只有一个pdf,则直接取
patentInstruction = patentInstructionList.get(0);
}
String filePath = fileUtils.getSystemPath() + patentInstruction.getUrl();
File pdfFile = new File(filePath);
if (patentInstructionList.size() == 0 || !pdfFile.exists()) { //若没有pdf或pdf文件不存在了,则跳过当前专利
BeanUtils.copyProperties(patent, patentDTO);
patentDTOs.add(patentDTO);
continue;
}
//判断缓存中是否有当前专利号的说明书pdf首页图片数据
Cache.ValueWrapper patentNoImgData = cacheManager.getCache("imgData").get(patentNo);
String imgData;
if (patentNoImgData == null) { //若没有,则手动转化并返回图片数据
//imgData = cyCacheUtil.getImgData(patentNo, pdfFile); //此时不进行缓存,防止缓存过多导致服务器宕机
imgData = this.getImgData(pdfFile);
} else { //若有,则从缓存取出图片数据后,再删除该缓存(防止缓存过多导致服务器宕机)
imgData = cyCacheUtil.getImgData(patentNo, pdfFile);
cyCacheUtil.deleteImgData(patentNo); //清除缓存
}
BeanUtils.copyProperties(patent, patentDTO);
patentDTO.setPdfFirstPage(imgData);
patentDTOs.add(patentDTO);
}
//开启一个线程去拿后面5件专利的pdf首页图片数据进行缓存
Thread thread = new Thread() {
@Override
public void run() {
//计算检索分页信息条件前面所有专利数量 beforeNum,作为接下来检索时的起始位置(sql语句:limit beforeNum-1, 5)
Long current = params.getCurrent();
Long size = params.getSize();
long beforeNum = current * size;
try {
threadRunTask(params, (int) beforeNum);
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
pageListResult.setCurrent(pageList.getCurrent());
pageListResult.setSize(pageList.getSize());
pageListResult.setPages(pageList.getPages());
pageListResult.setTotal(pageList.getTotal());
pageListResult.setRecords(patentDTOs);
return pageListResult;
}
/**
* 根据检索条件,将检索到的专利的pdf首页图片数据缓存到内存中
*
* @param params 检索条件
*/
public void threadRunTask(PatentVO params, Integer beforeNum) throws IOException {
//根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
List patents = patentMapper.getPageListNext5(params, beforeNum);
if (patents == null || patents.size() == 0) {
return;
}
List patentNos = patents.stream().map(Patent::getPatentNo).collect(Collectors.toList()); //取出专利号
//查询出所有pdf文档数据
List patentInstructions = this.list(new LambdaQueryWrapper().in(PatentInstruction::getPatentNo, patentNos));
//遍历专利,装载数据
for (Patent patent : patents) {
String patentNo = patent.getPatentNo();
List patentInstructionList = patentInstructions.stream().filter(patentInstruction -> patentInstruction.getPatentNo().equals(patentNo)).collect(Collectors.toList());
PatentInstruction patentInstruction = new PatentInstruction();
if (patentInstructionList.size() > 1) { //若有两个及以上pdf,则取授权文档
patentInstruction = patentInstructionList.stream().filter(item -> item.getType().equals(2)).collect(Collectors.toList()).get(0);
} else if (patentInstructionList.size() == 1) { //若只有一个pdf,则直接取
patentInstruction = patentInstructionList.get(0);
}
String filePath = fileUtils.getSystemPath() + patentInstruction.getUrl();
File pdfFile = new File(filePath);
if (patentInstructionList.size() == 0 || !pdfFile.exists()) { //若没有pdf或pdf文件不存在了,则跳过当前专利
continue;
}
//调用缓存方法,将当前专利号作为key,专利pdf首页文件图片数据作为value放入名称为"imgData"的缓存(key是唯一值,若缓存中已有当前专利号的key,则不会做任何操作)
cyCacheUtil.getImgData(patentNo, pdfFile);
}
}
public String getImgData(File pdfFile) throws IOException {
//pdf转图片方式二(用依赖pdfbox)
PDDocument doc = PDDocument.load(pdfFile);
String newFilePath = StringUtils.getUUID() + ".pdf";
File outputFile = new File(newFilePath);
PDFRenderer pdfRenderer = new PDFRenderer(doc);
// 提取的页码
int pageNumber = 0;
// 以300 dpi 读取存入 BufferedImage 对象
int dpi = 300;
RenderedImage buffImage = pdfRenderer.renderImageWithDPI(pageNumber, dpi, ImageType.RGB);
// 将 BufferedImage 写入到 png
ImageIO.write(buffImage, "png", outputFile);
doc.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileInputStream in = new FileInputStream(outputFile);
int bytesRead;
byte[] buffer = new byte[8192];
//读取pdf首页临时文件
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
//关闭读取流
in.close();
byte[] bytes = out.toByteArray();
String imgData = org.apache.commons.codec.binary.Base64.encodeBase64String(bytes);
//关闭写出流
out.close();
//最后记得删除pdf首页的临时文件
new File(newFilePath).delete();
return imgData;
}
}