Browse Source

编写查询专题库专利pdf首页清单接口(未完成已注释掉)

chendayu 2 years ago
parent
commit
30e7ef9104

+ 2 - 0
PAS/src/main/java/cn/cslg/pas/Application.java

@@ -3,10 +3,12 @@ package cn.cslg.pas;
 import cn.hutool.cron.CronUtil;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+@EnableCaching
 @SpringBootApplication
 public class Application {
 

+ 72 - 0
PAS/src/main/java/cn/cslg/pas/common/CyCacheUtil.java

@@ -0,0 +1,72 @@
+package cn.cslg.pas.common;
+
+import cn.cslg.pas.common.utils.StringUtils;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.rendering.ImageType;
+import org.apache.pdfbox.rendering.PDFRenderer;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Component;
+
+import javax.imageio.ImageIO;
+import java.awt.image.RenderedImage;
+import java.io.*;
+
+/**
+ * 缓存类,该类中定义一些用于缓存的方法
+ *
+ * @author chenyu
+ * @date 2023/9/15
+ */
+@Component
+public class CyCacheUtil implements Serializable {
+
+    /**
+     * 缓存指定专利号的说明书pdf首页的图片数据
+     *
+     * @param patentNo 专利号
+     * @param pdfFile  pdf文件
+     * @return 返回该专利号的说明书pdf首页的图片数据
+     */
+    @Cacheable(cacheNames = "imgData", key = "#patentNo")
+    public String getImgData(String patentNo, 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 = Base64.encodeBase64String(bytes);
+        //关闭写出流
+        out.close();
+        //最后记得删除pdf首页的临时文件
+        new File(newFilePath).delete();
+        return imgData;
+    }
+
+    @CacheEvict(cacheNames = "imgData", key = "#patentNo")
+    public void deleteImgData(String patentNo) {
+        //在名称为imgData的缓存中删除key为该专利号的缓存内容(即删除该专利号的说明书pdf首页的图片数据)
+    }
+
+}

+ 15 - 15
PAS/src/main/java/cn/cslg/pas/controller/PatentInstructionController.java

@@ -98,21 +98,21 @@ public class PatentInstructionController {
         }
     }
 
-//    @PostMapping("/pdfFirstPage")
-//    @Operation(summary = "合并导出专题库专利的pdf首页文件")
-//    public String exportPatentPdfFirstPages(@RequestBody PatentVO params) throws IOException {
-//        log.info("开始处理【合并导出专题库专利的pdf首页文件】的请求,请求参数为:{}", params);
-//        patentInstructionService.exportPatentPdfFirstPages(params);
-//        return Response.success();
-//    }
-//
-//    @Operation(summary = "查询专题库专利的pdf首页清单")
-//    @PostMapping("/queryPatentPdfFirstPages")
-//    public String queryPatentPdfFirstPages(@RequestBody PatentVO params) throws IOException {
-//        log.info("开始处理【查询专题库专利的pdf首页清单】的业务,业务参数为:{}", params);
-//        IPage<PatentDTO> patentDTOs = patentInstructionService.queryPatentPdfFirstPages(params);
-//        return Response.success(patentDTOs);
-//    }
+    @PostMapping("/pdfFirstPage")
+    @Operation(summary = "合并导出专题库专利的pdf首页文件")
+    public String exportPatentPdfFirstPages(@RequestBody PatentVO params) throws IOException {
+        log.info("开始处理【合并导出专题库专利的pdf首页文件】的请求,请求参数为:{}", params);
+        patentInstructionService.exportPatentPdfFirstPages(params);
+        return Response.success();
+    }
+
+    @Operation(summary = "查询专题库专利的pdf首页清单")
+    @PostMapping("/queryPatentPdfFirstPages")
+    public String queryPatentPdfFirstPages(@RequestBody PatentVO params) throws IOException {
+        log.info("开始处理【查询专题库专利的pdf首页清单】的业务,业务参数为:{}", params);
+        IPage<PatentDTO> patentDTOs = patentInstructionService.queryPatentPdfFirstPages(params);
+        return Response.success(patentDTOs);
+    }
 
 }
 

+ 333 - 282
PAS/src/main/java/cn/cslg/pas/service/PatentInstructionService.java

@@ -1,18 +1,25 @@
 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.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;
@@ -20,14 +27,31 @@ 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.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.File;
+import java.io.IOException;
+import java.util.List;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -47,6 +71,9 @@ public class PatentInstructionService extends ServiceImpl<PatentInstructionMappe
     private final TaskService taskService;
     private final MessageService messageService;
     private final FileManagerService fileManagerService;
+    private final CacheManager cacheManager;
+    private final RedisCacheManager redisCacheManager;
+    private final CyCacheUtil cyCacheUtil;
     private final FileUtils fileUtils;
     private final LoginUtils loginUtils;
 
@@ -288,287 +315,311 @@ public class PatentInstructionService extends ServiceImpl<PatentInstructionMappe
         });
     }
 
-//    /**
-//     * 合并导出专题库专利的pdf首页文件
-//     *
-//     * @param params 查询条件
-//     */
-//    public void exportPatentPdfFirstPages(PatentVO params) throws IOException {
-//        log.info("开始处理【合并导出专题库专利的pdf首页文件】的业务,业务参数为:{}", params);
-//
-//        //根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
-//        IPage<PatentDTO> pageList0 = patentService.getPageList(params);
-//        if (pageList0 == null || pageList0.getRecords() == null || pageList0.getRecords().size() == 0) {
-//            ThrowException.throwXiaoShiException("合并专利pdf首页文档失败,无专利信息!");
-//        }
-//
-//        int total = (int) pageList0.getTotal();  //专利总数(作为任务进度总数)
-//        long pages = pageList0.getPages();  //总页数(用来计算要检索几次)
-//
-//        ArrayList<String> 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<PatentDTO> pageList = patentService.getPageList(params);  //根据筛选条件分页查询专利清单
-//            List<PatentDTO> patents = pageList.getRecords();  //取出专利清单
-//            List<String> patentNos = patents.stream().map(PatentDTO::getPatentNo).collect(Collectors.toList());  //过滤取出专利号
-//
-//            //根据专利号patentNos查询出所有pdf文档数据
-//            List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
-//
-//            //遍历当前专利号清单
-//            for (String patentNo : patentNos) {
-//                List<PatentInstruction> 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<MultipartFile> multipartFiles = new ArrayList<>();
-//        multipartFiles.add(multipartFile);
-//        String res = fileManagerService.uploadFile(multipartFiles);
-//        JSONObject jsonObject = JSONObject.parseObject(res);
-//        List<Integer> fileIds = JSONArray.parseArray(jsonObject.get("data").toString(), Integer.class);
-//        res = fileManagerService.getSystemFileFromFMS(fileIds);
-//        List<SystemFile> 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);
-//    }
-//
-//    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<PatentDTO> queryPatentPdfFirstPages(PatentVO params) throws IOException {
-//        log.info("开始处理【查询专题库专利的pdf首页清单】的业务,业务参数为:{}", params);
-//
-//        //根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
-//        IPage<PatentDTO> pageList = patentService.getPageList(params);
-//        if (pageList == null || pageList.getRecords() == null || pageList.getRecords().size() == 0) {
-//            ThrowException.throwXiaoShiException("查询专题库专利的pdf首页清单失败,未获取到任何专利信息!");
-//        }
-//
-//        List<PatentDTO> patents = pageList.getRecords();  //取出专利清单
-//        List<String> patentNos = patents.stream().map(PatentDTO::getPatentNo).collect(Collectors.toList());  //过滤取出专利号
-//        //根据专利号patentNos查询出所有pdf文档数据
-//        List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
-//
-//        //遍历专利,装载数据
-//        for (PatentDTO patent : patents) {
-//            List<PatentInstruction> patentInstructionList = patentInstructions.stream().filter(patentInstruction -> patentInstruction.getPatentNo().equals(patent.getPatentNo())).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;
-//            }
-//
-//            //取出pdf首页并存入临时文件 outputFile
-//            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);
-//            //needDoc.close();
-//            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 data = Base64.encodeBase64String(bytes);
-//            patent.setPdfFirstPage(data);
-//            //关闭写出流
-//            out.close();
-//            //最后记得删除pdf首页的临时文件
-//            new File(newFilePath).delete();
-//        }
-//
-//        pageList.setRecords(patents);
-//        return pageList;
-//    }
+    /**
+     * 合并导出专题库专利的pdf首页文件
+     *
+     * @param params 查询条件
+     */
+    public void exportPatentPdfFirstPages(PatentVO params) throws IOException {
+        log.info("开始处理【合并导出专题库专利的pdf首页文件】的业务,业务参数为:{}", params);
+
+        //根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
+        IPage<PatentDTO> pageList0 = patentService.getPageList(params);
+        if (pageList0 == null || pageList0.getRecords() == null || pageList0.getRecords().size() == 0) {
+            ThrowException.throwXiaoShiException("合并专利pdf首页文档失败,无专利信息!");
+        }
+
+        int total = (int) pageList0.getTotal();  //专利总数(作为任务进度总数)
+        long pages = pageList0.getPages();  //总页数(用来计算要检索几次)
+
+        ArrayList<String> 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<PatentDTO> pageList = patentService.getPageList(params);  //根据筛选条件分页查询专利清单
+            List<PatentDTO> patents = pageList.getRecords();  //取出专利清单
+            List<String> patentNos = patents.stream().map(PatentDTO::getPatentNo).collect(Collectors.toList());  //过滤取出专利号
+
+            //根据专利号patentNos查询出所有pdf文档数据
+            List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
+
+            //遍历当前专利号清单
+            for (String patentNo : patentNos) {
+                List<PatentInstruction> 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<MultipartFile> multipartFiles = new ArrayList<>();
+        multipartFiles.add(multipartFile);
+        String res = fileManagerService.uploadFile(multipartFiles);
+        JSONObject jsonObject = JSONObject.parseObject(res);
+        List<Integer> fileIds = JSONArray.parseArray(jsonObject.get("data").toString(), Integer.class);
+        res = fileManagerService.getSystemFileFromFMS(fileIds);
+        List<SystemFile> 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);
+    }
+
+    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<PatentDTO> queryPatentPdfFirstPages(PatentVO params) throws IOException {
+        log.info("开始处理【查询专题库专利的pdf首页清单】的业务,业务参数为:{}", params);
+
+        //根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
+        IPage<PatentDTO> pageList = patentService.getPageList(params);
+        if (pageList == null || pageList.getRecords() == null || pageList.getRecords().size() == 0) {
+            ThrowException.throwXiaoShiException("查询专题库专利的pdf首页清单失败,未获取到任何专利信息!");
+        }
+
+        List<PatentDTO> patents = pageList.getRecords();  //取出专利清单
+        List<String> patentNos = patents.stream().map(PatentDTO::getPatentNo).collect(Collectors.toList());  //过滤取出专利号
+        //根据专利号patentNos查询出所有pdf文档数据
+        List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
+
+        //遍历专利,装载数据
+        for (PatentDTO patent : patents) {
+            String patentNo = patent.getPatentNo();
+            List<PatentInstruction> 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;
+            }
+
+            //解析当前专利号的pdf文件,将pdf首页转换为图片数据并返回,使用名称为"imgData"的缓存进行处理
+            String imgData = cyCacheUtil.getImgData(patentNo, pdfFile);
+            patent.setPdfFirstPage(imgData);
+
+        }
+
+        //开启一个线程继续去拿当前专利后面5件专利
+        Thread thread = new Thread() {
+            @Override
+            public void run() {
+                Long current = params.getCurrent();
+                //Long size = params.getSize();
+                //long beforeNum = current * size;
+                params.setCurrent(++current);
+                try {
+                    threadRunTask(params);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        };
+        thread.start();
+
+
+        pageList.setRecords(patents);
+        return pageList;
+    }
+
+    public void threadRunTask(PatentVO params) throws IOException {
+        //根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
+        IPage<PatentDTO> pageList = patentService.getPageList(params);
+        if (pageList == null || pageList.getRecords() == null || pageList.getRecords().size() == 0) {
+            return;
+        }
+        List<PatentDTO> patents = pageList.getRecords();  //取出专利清单
+        List<String> patentNos = patents.stream().map(PatentDTO::getPatentNo).collect(Collectors.toList());  //过滤取出专利号
+        //根据专利号patentNos查询出所有pdf文档数据
+        List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
+        //遍历专利,装载数据
+        for (PatentDTO patent : patents) {
+            String patentNo = patent.getPatentNo();
+            List<PatentInstruction> 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;
+            }
+
+            //解析当前专利号的pdf文件,将pdf首页转换为图片数据并返回,使用名称为"imgData"的缓存进行处理
+            cyCacheUtil.getImgData(patentNo, pdfFile);
+        }
+    }
+
 
 }