PatentInstructionService.java 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. package cn.cslg.pas.service;
  2. import cn.cslg.pas.common.CyCacheUtil;
  3. import cn.cslg.pas.common.core.base.Constants;
  4. import cn.cslg.pas.common.model.dto.PatentDTO;
  5. import cn.cslg.pas.common.model.dto.UploadFileDTO;
  6. import cn.cslg.pas.common.model.vo.PatentInstructionVO;
  7. import cn.cslg.pas.common.model.vo.PatentVO;
  8. import cn.cslg.pas.common.model.vo.SystemFile;
  9. import cn.cslg.pas.common.utils.*;
  10. import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
  11. import cn.cslg.pas.domain.Patent;
  12. import cn.cslg.pas.domain.PatentInstruction;
  13. import cn.cslg.pas.domain.Task;
  14. import cn.cslg.pas.mapper.PatentInstructionMapper;
  15. import cn.cslg.pas.mapper.PatentMapper;
  16. import cn.cslg.pas.service.upLoadPatent.MessageService;
  17. import cn.hutool.core.io.FileUtil;
  18. import cn.hutool.core.util.IdUtil;
  19. import cn.hutool.core.util.ZipUtil;
  20. import com.alibaba.fastjson.JSONArray;
  21. import com.alibaba.fastjson2.JSONObject;
  22. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  23. import com.baomidou.mybatisplus.core.metadata.IPage;
  24. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  25. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  26. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  27. import lombok.RequiredArgsConstructor;
  28. import lombok.extern.slf4j.Slf4j;
  29. import org.apache.pdfbox.multipdf.PDFMergerUtility;
  30. import org.apache.pdfbox.multipdf.Splitter;
  31. import org.apache.pdfbox.pdmodel.PDDocument;
  32. import org.apache.pdfbox.pdmodel.PDPage;
  33. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  34. import org.apache.pdfbox.pdmodel.common.PDRectangle;
  35. import org.apache.pdfbox.pdmodel.font.PDFont;
  36. import org.apache.pdfbox.pdmodel.font.PDType1Font;
  37. import org.apache.pdfbox.rendering.ImageType;
  38. import org.apache.pdfbox.rendering.PDFRenderer;
  39. import org.springframework.beans.BeanUtils;
  40. import org.springframework.cache.Cache;
  41. import org.springframework.cache.CacheManager;
  42. import org.springframework.context.annotation.Lazy;
  43. import org.springframework.data.redis.cache.RedisCacheManager;
  44. import org.springframework.scheduling.annotation.Async;
  45. import org.springframework.stereotype.Service;
  46. import org.springframework.transaction.annotation.Transactional;
  47. import org.springframework.transaction.interceptor.TransactionAspectSupport;
  48. import org.springframework.web.multipart.MultipartFile;
  49. import javax.imageio.ImageIO;
  50. import java.awt.*;
  51. import java.awt.image.RenderedImage;
  52. import java.io.ByteArrayOutputStream;
  53. import java.io.File;
  54. import java.io.FileInputStream;
  55. import java.io.IOException;
  56. import java.util.List;
  57. import java.util.*;
  58. import java.util.stream.Collectors;
  59. /**
  60. * <p>
  61. * 专利说明书 服务类
  62. * </p>
  63. *
  64. * @author 王岩
  65. * @since 2022-03-02
  66. */
  67. @Slf4j
  68. @Service
  69. @RequiredArgsConstructor(onConstructor_ = {@Lazy})
  70. public class PatentInstructionService extends ServiceImpl<PatentInstructionMapper, PatentInstruction> {
  71. private final PatentService patentService;
  72. private final PatentMapper patentMapper;
  73. private final TaskService taskService;
  74. private final MessageService messageService;
  75. private final FileManagerService fileManagerService;
  76. private final CacheManager cacheManager;
  77. private final CyCacheUtil cyCacheUtil;
  78. private final FileUtils fileUtils;
  79. private final LoginUtils loginUtils;
  80. public IPage<PatentInstruction> getPageList(PatentInstructionVO params) {
  81. LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
  82. if (StringUtils.isNotEmpty(params.getPatentNo())) {
  83. queryWrapper.like(PatentInstruction::getPatentNo, params.getPatentNo());
  84. }
  85. if (params.getType() != null) {
  86. queryWrapper.eq(PatentInstruction::getType, params.getType());
  87. }
  88. if (params.getPatentId() != null) {
  89. queryWrapper.eq(PatentInstruction::getPatentId, params.getPatentId());
  90. }
  91. IPage<PatentInstruction> pageList = this.page(new Page<>(params.getCurrent(), params.getSize()), queryWrapper);
  92. return pageList;
  93. }
  94. public List<PatentInstruction> getPatentInstructionByPatentNo(String patentNo) {
  95. LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
  96. queryWrapper.eq(PatentInstruction::getPatentNo, patentNo);
  97. return this.list(queryWrapper);
  98. }
  99. public List<PatentInstruction> getPatentInstructionByPatentNo(List<String> patentNo) {
  100. if (patentNo == null || patentNo.size() == 0) {
  101. return new ArrayList<>();
  102. }
  103. LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
  104. queryWrapper.in(PatentInstruction::getPatentNo, patentNo);
  105. return this.list(queryWrapper);
  106. }
  107. public PatentInstruction getPatentInstructionByPatentNoAndType(String patentNo, Integer type) {
  108. LambdaQueryWrapper<PatentInstruction> queryWrapper = new LambdaQueryWrapper<>();
  109. queryWrapper.eq(PatentInstruction::getType, type);
  110. queryWrapper.eq(PatentInstruction::getPatentNo, patentNo).last("Limit 1");
  111. return this.getOne(queryWrapper);
  112. }
  113. @Async("singleThreadAsyncTaskExecutor")
  114. @Transactional(rollbackFor = Exception.class)
  115. public void batchUpload(String url, Integer type, String remark, Integer userId) {
  116. String tempPath = null;
  117. try {
  118. String tempDirectoryName = IdUtil.simpleUUID();
  119. tempPath = fileUtils.getSystemPath(tempDirectoryName);
  120. File tempDirectory = new File(tempPath);
  121. if (!tempDirectory.exists()) {
  122. tempDirectory.mkdir();
  123. }
  124. ZipUtil.unzip(fileUtils.getSystemPath(url), tempPath);
  125. List<File> fileList = FileUtil.loopFiles(tempPath).stream().filter(item -> FileUtil.getType(item).equals("pdf")).collect(Collectors.toList());
  126. for (int i = 0; i < fileList.size(); i++) {
  127. File file = fileList.get(i);
  128. String fileName = file.getName();
  129. String patentNo = FileUtil.getPrefix(file);
  130. String saveName = IdUtil.simpleUUID() + ".pdf";
  131. String saveUrl = fileUtils.getDirectory(saveName);
  132. String savePath = fileUtils.getSystemPath(saveUrl);
  133. FileUtil.copy(file.getPath(), savePath, true);
  134. PatentInstruction temp = this.getPatentInstructionByPatentNoAndType(patentNo, type);
  135. if (temp == null) {
  136. temp = new PatentInstruction();
  137. } else {
  138. FileUtil.del(fileUtils.getSystemPath(temp.getUrl()));
  139. }
  140. temp.setPatentNo(patentNo);
  141. temp.setFileName(saveName);
  142. temp.setSize(FileUtil.size(file));
  143. temp.setUrl(saveUrl);
  144. temp.setRemark(remark);
  145. temp.setCreateBy(userId);
  146. temp.setType(type);
  147. temp.insertOrUpdate();
  148. Map<String, Object> data = new HashMap<>();
  149. data.put("index", i);
  150. data.put("total", fileList.size());
  151. WebSocketServer.sendInfo(Response.websocket(data, ResponseEnum.BATCH_UPLOAD_INSTRUCTION_TASK_SUCCESS), String.valueOf(userId));
  152. }
  153. } catch (Exception e) {
  154. e.printStackTrace();
  155. WebSocketServer.sendInfo(Response.error(ResponseEnum.BATCH_UPLOAD_INSTRUCTION_TASK_ERROR), String.valueOf(userId));
  156. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  157. } finally {
  158. FileUtil.del(tempPath);
  159. }
  160. }
  161. public String add(MultipartFile file, PatentInstruction patentInstruction) {
  162. UploadFileDTO fileDTO = fileUtils.uploadFile(file);
  163. patentInstruction.setCreateBy(loginUtils.getId());
  164. patentInstruction.setUrl(fileDTO.getPath());
  165. patentInstruction.setFileName(fileDTO.getFileName());
  166. patentInstruction.insert();
  167. return Response.success(patentInstruction.getId());
  168. }
  169. @Transactional
  170. public String edit(MultipartFile file, PatentInstruction patentInstruction) {
  171. this.deleteByPatentNoAndType(patentInstruction.getPatentNo(), patentInstruction.getType());
  172. if (StringUtils.isNotEmpty(patentInstruction.getUrl())) {
  173. FileUtil.del(fileUtils.getSystemPath(patentInstruction.getUrl()));
  174. }
  175. UploadFileDTO fileDTO = fileUtils.uploadFile(file);
  176. patentInstruction.setCreateBy(loginUtils.getId());
  177. patentInstruction.setUrl(fileDTO.getPath());
  178. patentInstruction.setFileName(fileDTO.getFileName());
  179. patentInstruction.setSize(fileDTO.getFileSize());
  180. patentInstruction.insert();
  181. return Response.success(true);
  182. }
  183. /**
  184. * 说明书pdf数据入库
  185. *
  186. * @param patentNo 专利号
  187. * @param pdf 装载pdf数据对象
  188. */
  189. @Transactional
  190. public String edit(String patentNo, UploadFileDTO pdf) {
  191. //先把实体类对象赋好值
  192. PatentInstruction patentInstruction = new PatentInstruction();
  193. patentInstruction.setUrl(pdf.getPath());
  194. patentInstruction.setFileName(pdf.getFileName());
  195. patentInstruction.setSize(pdf.getFileSize());
  196. patentInstruction.setPatentNo(patentNo);
  197. patentInstruction.setType(1);
  198. //根据专利号和pdf类型(1公开 2授权)查询该专利号是否已有公开的pdf
  199. List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 1));
  200. if (patentInstructions != null && patentInstructions.size() > 0) { //若有则更新
  201. patentInstruction.setId(patentInstructions.get(0).getId());
  202. this.updateById(patentInstruction);
  203. } else { //若没有则新增
  204. this.save(patentInstruction);
  205. }
  206. return Response.success(true);
  207. }
  208. @Transactional
  209. public String edit2(String patentNo, UploadFileDTO pdf2) {
  210. //先把实体类对象赋好值
  211. PatentInstruction patentInstruction = new PatentInstruction();
  212. patentInstruction.setUrl(pdf2.getPath());
  213. patentInstruction.setFileName(pdf2.getFileName());
  214. patentInstruction.setSize(pdf2.getFileSize());
  215. patentInstruction.setPatentNo(patentNo);
  216. patentInstruction.setType(2);
  217. //根据专利号和pdf类型(1公开 2授权)查询该专利号是否已有授权的pdf
  218. List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 2));
  219. //若有则更新
  220. if (patentInstructions != null && patentInstructions.size() > 0) {
  221. patentInstruction.setId(patentInstructions.get(0).getId());
  222. this.updateById(patentInstruction);
  223. } else { //若没有则新增
  224. this.save(patentInstruction);
  225. }
  226. return Response.success(true);
  227. }
  228. @Transactional
  229. public String edit12(String patentNo, UploadFileDTO pdf1, UploadFileDTO pdf2) {
  230. //处理公开pdf文档(更新或新增)
  231. PatentInstruction patentInstruction1 = new PatentInstruction();
  232. patentInstruction1.setUrl(pdf1.getPath());
  233. patentInstruction1.setFileName(pdf1.getFileName());
  234. patentInstruction1.setSize(pdf1.getFileSize());
  235. patentInstruction1.setPatentNo(patentNo);
  236. patentInstruction1.setType(1);
  237. //先查询库中是否已有该专利号的公开pdf文档
  238. List<PatentInstruction> patentInstructions1 = this.list(new LambdaQueryWrapper<PatentInstruction>().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 1));
  239. //若有则更新
  240. if (patentInstructions1 != null && patentInstructions1.size() > 0) {
  241. patentInstruction1.setId(patentInstructions1.get(0).getId());
  242. this.updateById(patentInstruction1);
  243. } else { //若没有则新增
  244. this.save(patentInstruction1);
  245. }
  246. //处理授权pdf文档(更新或新增)
  247. PatentInstruction patentInstruction2 = new PatentInstruction();
  248. patentInstruction2.setUrl(pdf2.getPath());
  249. patentInstruction2.setFileName(pdf2.getFileName());
  250. patentInstruction2.setSize(pdf2.getFileSize());
  251. patentInstruction2.setPatentNo(patentNo);
  252. patentInstruction2.setType(2);
  253. //再查询库中是否已有该专利号的授权pdf文档
  254. List<PatentInstruction> patentInstructions2 = this.list(new LambdaQueryWrapper<PatentInstruction>().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, 2));
  255. //若有则更新
  256. if (patentInstructions2 != null && patentInstructions2.size() > 0) {
  257. patentInstruction2.setId(patentInstructions2.get(0).getId());
  258. this.updateById(patentInstruction2);
  259. } else { //若没有则新增
  260. this.save(patentInstruction2);
  261. }
  262. return Response.success(true);
  263. }
  264. public String delete(Integer id) {
  265. PatentInstruction temp = this.getById(id);
  266. this.removeById(id);
  267. if (StringUtils.isNotEmpty(temp.getUrl())) {
  268. FileUtil.del(fileUtils.getSystemPath(temp.getUrl()));
  269. }
  270. return Response.success(true);
  271. }
  272. public void deleteByPatentNoAndType(String patentNo, Integer type) {
  273. this.remove(Wrappers.<PatentInstruction>lambdaQuery().eq(PatentInstruction::getPatentNo, patentNo).eq(PatentInstruction::getType, type));
  274. }
  275. public void importPatentInstruction(Integer userId, String tempPath, String patentIdPatentNoJson, String patentInstructionJson) {
  276. List<Patent> importPatentList = JsonUtils.jsonToList(patentIdPatentNoJson, Patent.class);
  277. List<PatentInstruction> importPatentInstructionList = JsonUtils.jsonToList(patentInstructionJson, PatentInstruction.class);
  278. List<PatentInstruction> localPatentInstructionList = this.getPatentInstructionByPatentNo(importPatentList.stream().map(Patent::getPatentNo).collect(Collectors.toList()));
  279. for (PatentInstruction patentInstruction : importPatentInstructionList) {
  280. String fileName = IdUtil.simpleUUID() + "." + FileUtil.extName(patentInstruction.getFileName());
  281. String saveUrl = fileUtils.getDirectory(fileName);
  282. String savePath = fileUtils.getSystemPath(saveUrl);
  283. String tempInstruction = tempPath + FileUtils.FILE_SEPARATOR + Constants.PATENT_INSTRUCTION_DIRECTORY_NAME + FileUtils.FILE_SEPARATOR + patentInstruction.getFileName();
  284. patentInstruction.setId(null);
  285. patentInstruction.setFileName(fileName);
  286. patentInstruction.setUrl(saveUrl);
  287. patentInstruction.setCreateBy(userId);
  288. patentInstruction.setCreateTime(new Date());
  289. if (FileUtil.exist(tempInstruction)) {
  290. patentInstruction.insert();
  291. FileUtil.copy(tempInstruction, savePath, true);
  292. }
  293. }
  294. localPatentInstructionList.forEach(item -> {
  295. item.deleteById();
  296. FileUtil.del(fileUtils.getSystemPath(item.getUrl()));
  297. });
  298. }
  299. /**
  300. * 合并导出专题库专利的pdf首页文件
  301. *
  302. * @param params 查询条件
  303. */
  304. public void exportPatentPdfFirstPages(PatentVO params) throws IOException {
  305. log.info("开始处理【合并导出专题库专利的pdf首页文件】的业务,业务参数为:{}", params);
  306. //根据筛选条件分页查询专利清单(本次查询目的只是获得专利总数和总页数)
  307. IPage<Patent> pageList0 = patentMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params);
  308. if (pageList0 == null || pageList0.getRecords() == null || pageList0.getRecords().size() == 0) {
  309. ThrowException.throwXiaoShiException("合并专利pdf首页文档失败,未查询到任何专利信息!");
  310. }
  311. int total = (int) pageList0.getTotal(); //专利总数(作为任务进度总数)
  312. long pages = pageList0.getPages(); //总页数(用来计算要检索几次)
  313. ArrayList<String> filePaths = new ArrayList<>(); //存放所有临时文件(说明书pdf首页的文件)路径
  314. String mergedFilePath = StringUtils.getUUID() + ".pdf"; //合并后的pdf文件路径
  315. PDFMergerUtility pdfMerger = new PDFMergerUtility(); //pdf合并工具
  316. //上传任务
  317. Task task = new Task()
  318. .setFileName(mergedFilePath)
  319. .setProjectId(params.getProjectId())
  320. .setType(6)
  321. .setCreateBy(loginUtils.getId())
  322. .setStartTime(DateUtils.getDateTime())
  323. .setTotal(total)
  324. .setStatus(6)
  325. .setDefaultNum(0)
  326. .setSuccessNum(0)
  327. .setTrueSuccessNum(0);
  328. taskService.save(task);
  329. //一页一页检索
  330. for (long i = 1; i <= pages; i++) {
  331. params.setCurrent(i);
  332. IPage<Patent> pageList = patentMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params);
  333. List<Patent> patents = pageList.getRecords(); //取出专利清单
  334. List<String> patentNos = patents.stream().map(Patent::getPatentNo).collect(Collectors.toList()); //过滤取出专利号
  335. //根据专利号patentNos查询出所有pdf文档数据
  336. List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
  337. //遍历当前专利号清单
  338. for (String patentNo : patentNos) {
  339. List<PatentInstruction> patentInstructionList = patentInstructions.stream().filter(item -> item.getPatentNo().equals(patentNo)).collect(Collectors.toList());
  340. //若有说明书pdf数据
  341. PatentInstruction patentInstruction = new PatentInstruction();
  342. if (patentInstructionList.size() > 1) { //若有多个,则过滤取出授权文档
  343. patentInstruction = patentInstructionList.stream().filter(item -> item.getType() == 2).collect(Collectors.toList()).get(0);
  344. } else if (patentInstructionList.size() == 1) { //若只有一个pdf,则直接取出
  345. patentInstruction = patentInstructionList.get(0);
  346. }
  347. String filePath = fileUtils.getSystemPath() + patentInstruction.getUrl();
  348. File pdfFile = new File(filePath);
  349. //若没有说明书pdf数据,则手写空白页显示该专利没有说明书pdf
  350. if (patentInstructionList.size() == 0 || !pdfFile.exists()) {
  351. //创建文件,设置页码
  352. PDDocument doc = new PDDocument();
  353. PDPage pageOne = new PDPage(PDRectangle.A4);
  354. doc.addPage(pageOne);
  355. //创建页面内容流
  356. PDPageContentStream contents = new PDPageContentStream(doc, pageOne, true, true, true);
  357. //设置要使用的字体类型
  358. //PDFont font = PDType1Font.COURIER_BOLD_OBLIQUE;
  359. PDFont font = PDType1Font.HELVETICA;
  360. //要写入的文本内容
  361. String message = "no pdf of " + patentNo;
  362. //设置字体大小
  363. float fontSize = 36.0f;
  364. PDRectangle pageSize = pageOne.getMediaBox();
  365. float stringWidth = font.getStringWidth(message) * fontSize / 1000f;
  366. //计算页中心位置
  367. int rotation = pageOne.getRotation();
  368. boolean rotate = rotation == 90 || rotation == 270;
  369. float pageWidth = rotate ? pageSize.getHeight() : pageSize.getWidth();
  370. float pageHeight = rotate ? pageSize.getWidth() : pageSize.getHeight();
  371. double centeredXPosition = rotate ? pageHeight / 2f : (pageWidth - stringWidth) / 2f;
  372. double centeredYPosition = rotate ? (pageWidth - stringWidth) / 2f : pageHeight / 2f;
  373. contents.beginText();
  374. //设置字体和大小
  375. contents.setFont(font, fontSize);
  376. //设置文本颜色
  377. contents.setNonStrokingColor(Color.BLACK);
  378. if (rotate) {
  379. // rotate the text according to the page rotation
  380. contents.setTextRotation(Math.PI / 2, centeredXPosition, centeredYPosition);
  381. } else {
  382. contents.setTextTranslation(centeredXPosition, centeredYPosition);
  383. }
  384. //开始写出文本内容
  385. contents.showText(message);
  386. contents.endText();
  387. //记得关闭流对象要不然是无法成功保存pdf文档的
  388. contents.close();
  389. //创建临时文件 newFilePath
  390. String newFilePath = StringUtils.getUUID() + ".pdf";
  391. //将pdf首页写入临时文件
  392. doc.save(newFilePath);
  393. filePaths.add(newFilePath);
  394. pdfMerger.addSource(newFilePath);
  395. doc.close();
  396. } else {
  397. PDDocument doc = PDDocument.load(pdfFile);
  398. Splitter splitter = new Splitter();
  399. splitter.setStartPage(1);
  400. splitter.setEndPage(1);
  401. PDDocument needDoc = splitter.split(doc).get(0);
  402. String newFilePath = StringUtils.getUUID() + ".pdf";
  403. needDoc.save(newFilePath);
  404. filePaths.add(newFilePath);
  405. pdfMerger.addSource(newFilePath);
  406. needDoc.close();
  407. doc.close();
  408. }
  409. //更新任务表(完成数量+1)并发送进度
  410. task.setSuccessNum(task.getSuccessNum() + 1);
  411. task.setTrueSuccessNum(task.getTrueSuccessNum() + 1);
  412. sendMessage(total, task);
  413. }
  414. }
  415. // 设置合并生成pdf文件的名称
  416. pdfMerger.setDestinationFileName(mergedFilePath);
  417. // 合并PDF
  418. pdfMerger.mergeDocuments();
  419. //若最终合并成的pdf文件不存在
  420. if (!new File(mergedFilePath).exists()) {
  421. ThrowException.throwXiaoShiException("当前批次所有专利的说明书文档不存在或已丢失");
  422. }
  423. //File文件转成MultipartFile,上传文件至服务器,获得文件信息,更新任务表数据
  424. MultipartFile multipartFile = FileToMultipartFileUtiles.fileToMultipartFile(mergedFilePath);
  425. ArrayList<MultipartFile> multipartFiles = new ArrayList<>();
  426. multipartFiles.add(multipartFile);
  427. String res = fileManagerService.uploadFile(multipartFiles);
  428. JSONObject jsonObject = JSONObject.parseObject(res);
  429. List<Integer> fileIds = JSONArray.parseArray(jsonObject.get("data").toString(), Integer.class);
  430. res = fileManagerService.getSystemFileFromFMS(fileIds);
  431. List<SystemFile> systemFiles = JSONArray.parseArray(res, SystemFile.class);
  432. SystemFile systemFile = systemFiles.get(0);
  433. Task updateTask = new Task();
  434. updateTask.setId(task.getId());
  435. updateTask.setSystemFileId(fileIds.get(0));
  436. updateTask.setUrl(systemFile.getFilePath().substring(systemFile.getFilePath().indexOf("file") + 4));
  437. updateTask.setFileSize(Long.valueOf(systemFile.getFileLength()));
  438. taskService.updateById(updateTask);
  439. //最后要记得删除所有PDF首页临时文件
  440. for (String filePath : filePaths) { //删除每个pdf首页文件
  441. new File(filePath).delete();
  442. }
  443. //删除最终合并的pdf首页文件
  444. new File(mergedFilePath).delete();
  445. }
  446. /**
  447. * 更新任务表(完成数量+1)、发送websocket进度
  448. *
  449. * @param total 任务专利总数量
  450. * @param task 任务对象
  451. */
  452. private void sendMessage(int total, Task task) {
  453. //更新任务表(完成数量+1),并发送进度+1
  454. Task updateTask = new Task();
  455. updateTask.setId(task.getId());
  456. updateTask.setSuccessNum(task.getSuccessNum());
  457. updateTask.setTrueSuccessNum(task.getTrueSuccessNum());
  458. taskService.updateById(updateTask);
  459. long percentage = (long) Math.floor((task.getSuccessNum() + 0D) / total * 100D);
  460. //当全部完成时
  461. if (task.getSuccessNum().equals(total)) {
  462. percentage = 100L;
  463. //任务表更新最终数据
  464. task.setStatus(2);
  465. updateTask.setStatus(task.getStatus());
  466. updateTask.setEndTime(DateUtils.getDateTime());
  467. taskService.updateById(updateTask);
  468. }
  469. //websocket发送进度
  470. messageService.sendWebsocketMessage(task, total, task.getSuccessNum(), percentage);
  471. }
  472. /**
  473. * pdf转图片方法Demo
  474. *
  475. * @param inputFile
  476. * @param outputFile
  477. */
  478. public void generateBookIamge(File inputFile, File outputFile) {
  479. try {
  480. PDDocument doc = PDDocument.load(inputFile);
  481. PDFRenderer pdfRenderer = new PDFRenderer(doc);
  482. // 提取的页码
  483. int pageNumber = 0;
  484. // 以300 dpi 读取存入 BufferedImage 对象
  485. int dpi = 300;
  486. RenderedImage buffImage = pdfRenderer.renderImageWithDPI(pageNumber, dpi, ImageType.RGB);
  487. // 将 BufferedImage 写入到 png
  488. ImageIO.write(buffImage, "png", outputFile);
  489. // 关闭文档
  490. doc.close();
  491. } catch (Exception e) {
  492. e.printStackTrace();
  493. }
  494. }
  495. /**
  496. * 查询专题库专利的pdf首页清单
  497. *
  498. * @param params 查询条件
  499. */
  500. public IPage<PatentDTO> queryPatentPdfFirstPages(PatentVO params) throws IOException {
  501. log.info("开始处理【查询专题库专利的pdf首页图片清单】的业务,业务参数为:{}", params);
  502. IPage<PatentDTO> pageListResult = new Page<>();
  503. ArrayList<PatentDTO> patentDTOs = new ArrayList<>();
  504. //根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
  505. IPage<Patent> pageList = patentMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params);
  506. if (pageList == null || pageList.getRecords() == null || pageList.getRecords().size() == 0) {
  507. ThrowException.throwXiaoShiException("查询专题库专利的pdf首页图片清单失败,未获取到任何专利信息!");
  508. }
  509. List<Patent> patents = pageList.getRecords(); //取出专利清单
  510. List<String> patentNos = patents.stream().map(Patent::getPatentNo).collect(Collectors.toList()); //取出专利号
  511. //查询出所有pdf文档数据
  512. List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
  513. //遍历专利,装载数据
  514. for (Patent patent : patents) {
  515. PatentDTO patentDTO = new PatentDTO();
  516. String patentNo = patent.getPatentNo();
  517. List<PatentInstruction> patentInstructionList = patentInstructions.stream().filter(patentInstruction -> patentInstruction.getPatentNo().equals(patentNo)).collect(Collectors.toList());
  518. PatentInstruction patentInstruction = new PatentInstruction();
  519. if (patentInstructionList.size() > 1) { //若有两个及以上pdf,则取授权文档
  520. patentInstruction = patentInstructionList.stream().filter(item -> item.getType().equals(2)).collect(Collectors.toList()).get(0);
  521. } else if (patentInstructionList.size() == 1) { //若只有一个pdf,则直接取
  522. patentInstruction = patentInstructionList.get(0);
  523. }
  524. String filePath = fileUtils.getSystemPath() + patentInstruction.getUrl();
  525. File pdfFile = new File(filePath);
  526. if (patentInstructionList.size() == 0 || !pdfFile.exists()) { //若没有pdf或pdf文件不存在了,则跳过当前专利
  527. BeanUtils.copyProperties(patent, patentDTO);
  528. patentDTOs.add(patentDTO);
  529. continue;
  530. }
  531. //判断缓存中是否有当前专利号的说明书pdf首页图片数据
  532. Cache.ValueWrapper patentNoImgData = cacheManager.getCache("imgData").get(patentNo);
  533. String imgData;
  534. if (patentNoImgData == null) { //若没有,则手动转化并返回图片数据
  535. //imgData = cyCacheUtil.getImgData(patentNo, pdfFile); //此时不进行缓存,防止缓存过多导致服务器宕机
  536. imgData = this.getImgData(pdfFile);
  537. } else { //若有,则从缓存取出图片数据后,再删除该缓存(防止缓存过多导致服务器宕机)
  538. imgData = cyCacheUtil.getImgData(patentNo, pdfFile);
  539. cyCacheUtil.deleteImgData(patentNo); //清除缓存
  540. }
  541. BeanUtils.copyProperties(patent, patentDTO);
  542. patentDTO.setPdfFirstPage(imgData);
  543. patentDTOs.add(patentDTO);
  544. }
  545. //开启一个线程去拿后面5件专利的pdf首页图片数据进行缓存
  546. Thread thread = new Thread() {
  547. @Override
  548. public void run() {
  549. //计算检索分页信息条件前面所有专利数量 beforeNum,作为接下来检索时的起始位置(sql语句:limit beforeNum-1, 5)
  550. Long current = params.getCurrent();
  551. Long size = params.getSize();
  552. long beforeNum = current * size;
  553. try {
  554. threadRunTask(params, (int) beforeNum);
  555. } catch (IOException e) {
  556. e.printStackTrace();
  557. }
  558. }
  559. };
  560. thread.start();
  561. pageListResult.setCurrent(pageList.getCurrent());
  562. pageListResult.setSize(pageList.getSize());
  563. pageListResult.setPages(pageList.getPages());
  564. pageListResult.setTotal(pageList.getTotal());
  565. pageListResult.setRecords(patentDTOs);
  566. return pageListResult;
  567. }
  568. /**
  569. * 根据检索条件,将检索到的专利的pdf首页图片数据缓存到内存中
  570. *
  571. * @param params 检索条件
  572. */
  573. public void threadRunTask(PatentVO params, Integer beforeNum) throws IOException {
  574. //根据筛选条件分页查询专利清单(这一次查询目的只是获得专利总数和总页数)
  575. List<Patent> patents = patentMapper.getPageListNext5(params, beforeNum);
  576. if (patents == null || patents.size() == 0) {
  577. return;
  578. }
  579. List<String> patentNos = patents.stream().map(Patent::getPatentNo).collect(Collectors.toList()); //取出专利号
  580. //查询出所有pdf文档数据
  581. List<PatentInstruction> patentInstructions = this.list(new LambdaQueryWrapper<PatentInstruction>().in(PatentInstruction::getPatentNo, patentNos));
  582. //遍历专利,装载数据
  583. for (Patent patent : patents) {
  584. String patentNo = patent.getPatentNo();
  585. List<PatentInstruction> patentInstructionList = patentInstructions.stream().filter(patentInstruction -> patentInstruction.getPatentNo().equals(patentNo)).collect(Collectors.toList());
  586. PatentInstruction patentInstruction = new PatentInstruction();
  587. if (patentInstructionList.size() > 1) { //若有两个及以上pdf,则取授权文档
  588. patentInstruction = patentInstructionList.stream().filter(item -> item.getType().equals(2)).collect(Collectors.toList()).get(0);
  589. } else if (patentInstructionList.size() == 1) { //若只有一个pdf,则直接取
  590. patentInstruction = patentInstructionList.get(0);
  591. }
  592. String filePath = fileUtils.getSystemPath() + patentInstruction.getUrl();
  593. File pdfFile = new File(filePath);
  594. if (patentInstructionList.size() == 0 || !pdfFile.exists()) { //若没有pdf或pdf文件不存在了,则跳过当前专利
  595. continue;
  596. }
  597. //调用缓存方法,将当前专利号作为key,专利pdf首页文件图片数据作为value放入名称为"imgData"的缓存(key是唯一值,若缓存中已有当前专利号的key,则不会做任何操作)
  598. cyCacheUtil.getImgData(patentNo, pdfFile);
  599. }
  600. }
  601. public String getImgData(File pdfFile) throws IOException {
  602. //pdf转图片方式二(用依赖pdfbox)
  603. PDDocument doc = PDDocument.load(pdfFile);
  604. String newFilePath = StringUtils.getUUID() + ".pdf";
  605. File outputFile = new File(newFilePath);
  606. PDFRenderer pdfRenderer = new PDFRenderer(doc);
  607. // 提取的页码
  608. int pageNumber = 0;
  609. // 以300 dpi 读取存入 BufferedImage 对象
  610. int dpi = 300;
  611. RenderedImage buffImage = pdfRenderer.renderImageWithDPI(pageNumber, dpi, ImageType.RGB);
  612. // 将 BufferedImage 写入到 png
  613. ImageIO.write(buffImage, "png", outputFile);
  614. doc.close();
  615. ByteArrayOutputStream out = new ByteArrayOutputStream();
  616. FileInputStream in = new FileInputStream(outputFile);
  617. int bytesRead;
  618. byte[] buffer = new byte[8192];
  619. //读取pdf首页临时文件
  620. while ((bytesRead = in.read(buffer)) != -1) {
  621. out.write(buffer, 0, bytesRead);
  622. }
  623. //关闭读取流
  624. in.close();
  625. byte[] bytes = out.toByteArray();
  626. String imgData = org.apache.commons.codec.binary.Base64.encodeBase64String(bytes);
  627. //关闭写出流
  628. out.close();
  629. //最后记得删除pdf首页的临时文件
  630. new File(newFilePath).delete();
  631. return imgData;
  632. }
  633. }