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; } }