From e93edf3bbbdf2f6e5e4073dfca09f14c699b6572 Mon Sep 17 00:00:00 2001 From: super_liu <396572590@qq.com> Date: Wed, 11 Aug 2021 17:19:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20convert=20?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2pdf=E5=AD=90=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ActSarItemsEOService.java | 2 +- adc-da-convert/pom.xml | 260 +++++++++++++++++ .../da/convert/common/ConvertStateEnum.java | 19 ++ .../adc/da/convert/common/DocConverter.java | 265 ++++++++++++++++++ .../da/convert/common/DocConverterPdf.java | 243 ++++++++++++++++ .../da/convert/common/DocConverterPdfOld.java | 225 +++++++++++++++ .../adc/da/convert/common/PDFEditUtils.java | 34 +++ .../com/adc/da/convert/common/SplitPdf.java | 169 +++++++++++ .../src/main/lib/jodconverter-2.2.2.jar | Bin 0 -> 32054 bytes pom.xml | 3 +- 10 files changed, 1218 insertions(+), 2 deletions(-) create mode 100644 adc-da-convert/pom.xml create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java create mode 100644 adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java create mode 100644 adc-da-convert/src/main/lib/jodconverter-2.2.2.jar diff --git a/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java b/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java index 670dde45..57af35b3 100644 --- a/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java +++ b/adc-da-activiti/src/main/java/com/adc/da/workFlow/service/ActSarItemsEOService.java @@ -121,7 +121,7 @@ public class ActSarItemsEOService { } /*** - * @Description: 标准解读流程入库" + * @Description: 国内外标准流程入库" * @Author: yangxuenan * @Date: 2020/12/7 13:48 * @Param: [standJson] diff --git a/adc-da-convert/pom.xml b/adc-da-convert/pom.xml new file mode 100644 index 00000000..43028d98 --- /dev/null +++ b/adc-da-convert/pom.xml @@ -0,0 +1,260 @@ + + + + foton-slrs-system-rest + com.adc + 3.0.0 + + 4.0.0 + + adc-da-convert + + UTF-8 + UTF-8 + 1.7 + 1.7 + 1.7 + 4.3.9.RELEASE + 3.4.0 + 1.4.0-RC2 + 4.1.2 + + + + + adc + http://60.247.58.121:8182/nexus/content/groups/public + + true + + + true + + + + + + + + thirdparty + Nexus Thirdparty Repository + http://60.247.58.121:8182/nexus/content/repositories/thirdparty/ + + + + + + + com.adc + adc-da-swagger + 2.0.0 + + + com.adc + adc-da-base + 2.0.0 + + + com.adc + adc-da-sys + 3.0.0 + + + com.adc + adc-da-util + 2.2.4 + + + org.bouncycastle + bcprov-jdk14 + + + + + org.springframework + spring-tx + ${spring.version} + + + org.springframework + spring-web + ${spring.version} + + + org.mybatis + mybatis + ${mybatis.version} + + + javax.validation + validation-api + 2.0.1.Final + + + + org.apache.shiro + shiro-core + ${shiro.version} + + + + com.adc + adc-da-excel + 2.0.0 + + + + org.apache.poi + poi + ${poi.version} + + + org.apache.poi + poi-ooxml + ${poi.version} + + + org.apache.poi + poi-ooxml-schemas + ${poi.version} + + + org.apache.poi + poi-scratchpad + ${poi.version} + true + + + + + + com.adc + adc-da-file + RELEASE + + + com.adc + adc-da-file + 2.0.0 + + + + + com.servlets + cos + 05Nov2002 + + + + com.artofsolving + jodconverter + system + 2.2.2 + ${basedir}/src/main/lib/jodconverter-2.2.2.jar + + + org.openoffice + juh + 3.0.1 + + + org.openoffice + jurt + 3.0.1 + + + org.openoffice + ridl + 3.0.1 + + + org.slf4j + slf4j-jdk14 + 1.7.21 + test + + + org.openoffice + unoil + 3.0.1 + + + com.thoughtworks.xstream + xstream + 1.3.1 + + + + + + com.itextpdf + kernel + 7.0.4 + + + com.itextpdf + io + 7.0.4 + + + com.itextpdf + layout + 7.0.4 + + + com.itextpdf + forms + 7.0.4 + + + com.itextpdf + pdfa + 7.0.4 + + + com.itextpdf + pdftest + 7.0.4 + + + org.slf4j + slf4j-log4j12 + 1.7.18 + + + + + org.springframework.boot + spring-boot-starter-amqp + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + \ No newline at end of file diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java new file mode 100644 index 00000000..9f573722 --- /dev/null +++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/ConvertStateEnum.java @@ -0,0 +1,19 @@ +package com.adc.da.convert.common; + +public enum ConvertStateEnum { + NO_CONVERT(0,"未转换"),CONVERING(1,"转换中"),CONVERT_SUCCESS(2,"转换成功"),CONVERT_ERROR(3,"转换失败"); + + private int value; + private String lable; + + private ConvertStateEnum(int value, String lable) { + this.value = value; + this.lable = lable; + } + public int getValue() { + return value; + } + public String getLable() { + return lable; + } +} diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java new file mode 100644 index 00000000..30d1d95e --- /dev/null +++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverter.java @@ -0,0 +1,265 @@ +package com.adc.da.convert.common; + +import com.artofsolving.jodconverter.DocumentConverter; +import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection; +import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection; +import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter; +import com.itextpdf.kernel.pdf.PdfReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; + +import java.io.*; + +/** + * @Author yangxuenan + * @Description 文档转换 + * Date 2018/8/24 13:44 + * @Param + * @return + **/ +public class DocConverter { + + private static final Logger logger = LoggerFactory.getLogger(DocConverter.class); + // 环境 1:windows 2:linux + private static final int ENVIRONMENT = 1; + // (只涉及pdf2swf路径问题) + private String fileString; + // 输入路径 ,如果不设置就输出在默认的位置 + private String outputPath = ""; + //转化文件名称 + private String fileName; + //转换pdf文件 + private File pdfFile; + //转换成swf文件 + private File swfFile; + //待转换doc文件 + private File docFile; + //为文件加水印后文件路径 + String waterPdfPath; + + @Value("${convert.host}") + private String convertHost; + + public DocConverter(String fileString,String fileType) { + ini(fileString,fileType); + } + + /** + * @Author yangxuenan + * @Description 重新设置file + * Date 2018/8/24 13:50 + * @Param [fileString, fileType] + * @return void + **/ + public void setFile(String fileString,String fileType) { + ini(fileString,fileType); + } + + /** + * @Author yangxuenan + * @Description 初始化 + * Date 2018/8/24 13:50 + * @Param [fileString, fileType] + * @return void + **/ + private void ini(String fileString,String fileType) { + this.fileString = fileString; + fileName = fileString.substring(0, fileString.lastIndexOf(".")); + //判断文件类型,进行不同操作 + if(".doc".equals(fileType) || ".docx".equals(fileType)){ + docFile = new File(fileString); + pdfFile = new File(fileName + ".pdf"); + swfFile = new File(fileName + ".swf"); + } else if (".pdf".equals(fileType)){ + pdfFile = new File(fileName + ".pdf"); + swfFile = new File(fileName + ".swf"); + } + } + + /** + * @Author yangxuenan + * @Description 转为PDF + * Date 2018/8/24 13:50 + * @Param [] + * @return void + **/ + private void doc2pdf() throws Exception { + if (docFile.exists()) { + if (!pdfFile.exists()) { + logger.info("转换服务地址接口:"+convertHost); + //连接openOffice + OpenOfficeConnection connection = new SocketOpenOfficeConnection(convertHost,8100); + try { + connection.connect(); + //使用openOffice将doc文件转换问pdf文件 + DocumentConverter converter = new OpenOfficeDocumentConverter(connection); + converter.convert(docFile, pdfFile); + // 关闭连接 + connection.disconnect(); + logger.info("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****"); + } catch (java.net.ConnectException e) { + logger.error(e.getMessage(),e); + logger.info("****swf转换器异常,openoffice服务未启动!****"); + throw e; + } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) { + logger.error(e.getMessage(),e); + logger.info("****swf转换器异常,读取转换文件失败****"); + throw e; + } catch (Exception e) { + logger.error(e.getMessage(),e); + throw e; + } + } else { + logger.info("****已经转换为pdf,不需要再进行转化****"); + } + } else { + logger.info("****swf转换器异常,需要转换的文档不存在,无法转换****"); + } + } + + /** + * @Author yangxuenan + * @Description 转换成 swf + * Date 2018/8/24 13:51 + * @Param [fileType] + * @return void + **/ + /*private void pdf2swf(String fileType) throws Exception { + Runtime r = Runtime.getRuntime(); + if (!swfFile.exists()) { + if (pdfFile.exists()) { + // windows环境处理 + if (ENVIRONMENT == 1) { + try { + //使用swfTools工具将pdf文件转换为swf文件 + //String paperSwfFile = swfFile.getPath().replace(".swf","%.swf"); + Process p = r.exec("G:/swftTools/pdf2swf.exe "+ waterPdfPath + " -o "+ swfFile.getPath() + " -f -T 9 -t -s languagedir=G:/xpdf/xpdf-chinese-simplified"); + logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****"); + //如果源文件为doc类文件,将过渡的pdf文件删除 + if(".doc".equals(fileType) || ".docx".equals(fileType)){ + if (pdfFile.exists()) { + if(!pdfFile.delete()){ + logger.error("文件删除失败!!!"); + } + } + } + } catch (IOException e) { + logger.error(e.getMessage(),e); + throw e; + } + } else if (ENVIRONMENT == 2) {// linux环境处理 + try { + Process p = r.exec("pdf2swf " + pdfFile.getPath() + + " -o " + swfFile.getPath() + " -f -T 9 -t -s storeallcharacters"); + logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****"); + if (pdfFile.exists()) { + if(!pdfFile.delete()){ + logger.error("文件删除失败!!!"); + } + } + } catch (Exception e) { + logger.error(e.getMessage(),e); + throw e; + } + } + } else { + logger.info("****pdf不存在,无法转换****"); + } + } else { + logger.info("****swf已经存在不需要转换****"); + } + }*/ + + static String loadStream(InputStream in) throws IOException { + + int ptr = 0; + in = new BufferedInputStream(in); + StringBuilder buffer = new StringBuilder(); + + while ((ptr = in.read()) != -1) { + buffer.append((char) ptr); + } + + return buffer.toString(); + } + + /** + * @Author yangxuenan + * @Description 转换主方法 + * Date 2018/8/24 13:51 + * @Param [fileType] + * @return boolean + **/ + public boolean conver(String fileType) { + + if (swfFile.exists()) { + logger.info("****swf转换器开始工作,该文件已经转换为swf****"); + return true; + } + + if (ENVIRONMENT == 1) { + logger.info("****swf转换器开始工作,当前设置运行环境windows****"); + } else { + logger.info("****swf转换器开始工作,当前设置运行环境linux****"); + } + try { + //判断待转换文件类型,如果为doc文件需要先转为pdf类型文件 + if(".doc".equals(fileType) || ".docx".equals(fileType)){ + doc2pdf(); +// pdf2swf(fileType); + } else if (".pdf".equals(fileType)){ +// pdf2swf(fileType); + } + + } catch (Exception e) { + logger.error(e.getMessage(),e); + return false; + } + + if (swfFile.exists()) { + return true; + } else { + return false; + } + } + + /** + * @Author yangxuenan + * @Description 返回文件路径 + * Date 2018/8/24 13:52 + * @Param [] + * @return java.lang.String + **/ + public String getswfPath() { + if (swfFile.exists()) { + //获取转换后的swf文件路径 + String tempString = swfFile.getPath(); + tempString = tempString.replaceAll("\\\\", "/"); + return tempString; + } else { + return ""; + } + + } + + /** + * @Author yangxuenan + * @Description 设置输出路径 + * Date 2018/8/24 13:52 + * @Param [outputPath] + * @return void + **/ + public void setOutputPath(String outputPath) { + this.outputPath = outputPath; + if (!outputPath.equals("")) { + String realName = fileName.substring(fileName.lastIndexOf("/"), + fileName.lastIndexOf(".")); + if (outputPath.charAt(outputPath.length()) == '/') { + swfFile = new File(outputPath + realName + ".swf"); + } + } + } + + +} diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java new file mode 100644 index 00000000..6294d314 --- /dev/null +++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdf.java @@ -0,0 +1,243 @@ +package com.adc.da.convert.common; + +import com.artofsolving.jodconverter.DocumentConverter; +import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection; +import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection; +import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter; +import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.*; + +public class DocConverterPdf { + + private static final Logger logger = LoggerFactory.getLogger(DocConverterPdf.class); + + private static final int ENVIRONMENT = 1;// 环境 1:windows 2:linux + private String fileString;// (只涉及pdf2swf路径问题) + private String outputPath = "";// 输入路径 ,如果不设置就输出在默认的位置 + private String fileName; + private File pdfFile; + private File convertPdfFile; + private File swfFile; + private File docFile; + String waterPdfPath; + + private String convertHost; + + public DocConverterPdf(String fileString, String fileType) { + ini(fileString,fileType); + } + + /** + * 重新设置file + * + * @param fileString + */ + public void setFile(String fileString,String fileType) { + ini(fileString,fileType); + } + + /** + * 初始化 + * + * @param fileString + */ + private void ini(String fileString,String fileType) { + this.fileString = fileString; + fileName = fileString.substring(0, fileString.lastIndexOf(".")); + if(".doc".equals(fileType.toLowerCase()) || ".docx".equals(fileType.toLowerCase()) || ".xlsx".equals(fileType.toLowerCase()) || ".xls".equals(fileType.toLowerCase()) || ".ppt".equals(fileType.toLowerCase()) || ".pptx".equals(fileType.toLowerCase())){ + docFile = new File(fileString); + convertPdfFile=new File(fileName+"_C"+ ".pdf"); + pdfFile = new File(fileName + ".pdf"); + swfFile = new File(fileName + ".swf"); + } else if (".pdf".equals(fileType)){ + pdfFile = new File(fileName + ".pdf"); + swfFile = new File(fileName + ".swf"); + } + } + + /** + * 转为PDF + * + * @param + */ + private void doc2pdf() throws Exception { + if (!pdfFile.exists()) { + OpenOfficeConnection connection = null; + logger.info("转换服务地址接口:"+convertHost); + try { + if(StringUtils.isNotBlank(convertHost)){ + connection = new SocketOpenOfficeConnection(convertHost,8100); + }else{ + connection = new SocketOpenOfficeConnection(8100); + } + connection.connect(); + DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection); + converter.convert(docFile, convertPdfFile); + + //addWaterToPdf(pdfFile,userId); + + // close the connection + connection.disconnect(); + // 开始设置PDF文档相关属性保证其安全性 + logger.info("开始设置转换后的PDF文件安全性相关设置"); + PDFEditUtils.setPDFFileSecurity(pdfFile.getAbsolutePath(),convertPdfFile.getAbsolutePath()); + logger.info("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****"); + } catch (java.net.ConnectException e) { + logger.error(e.getMessage(),e); + logger.info("****pdf转换器异常,openoffice服务未启动!****"); + throw e; + } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) { + logger.error(e.getMessage(),e); + logger.info("****pdf转换器异常,读取转换文件失败****"); + throw e; + } catch (Exception e) { + logger.error(e.getMessage(),e); + throw e; + } + } else { + logger.info("****已经转换为pdf,不需要再进行转化****"); + } + } + + /** + * 转换成 swf + */ + @SuppressWarnings("unused") + /*private void pdf2swf(String fileType) throws Exception { + Runtime r = Runtime.getRuntime(); + if (!swfFile.exists()) { + if (pdfFile.exists()) { + if (ENVIRONMENT == 1) {// windows环境处理 + try { + //String paperSwfFile = swfFile.getPath().replace(".swf","%.swf"); + Process p = r.exec("G:/swftTools/pdf2swf.exe "+ waterPdfPath + " -o "+ swfFile.getPath() + " -f -T 9 -t -s languagedir=G:/xpdf/xpdf-chinese-simplified"); + logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****"); + if(".doc".equals(fileType) || ".docx".equals(fileType)){ + *//*if (pdfFile.exists()) { + pdfFile.delete(); + }*//* + } + } catch (IOException e) { + logger.error(e.getMessage(),e); + throw e; + } + } else if (ENVIRONMENT == 2) {// linux环境处理 + try { + Process p = r.exec("pdf2swf " + pdfFile.getPath() + + " -o " + swfFile.getPath() + " -f -T 9 -t -s storeallcharacters"); + logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****"); + if (pdfFile.exists()) { + if(!pdfFile.delete()){ + logger.error("文件删除失败!!!"); + } + } + } catch (Exception e) { + logger.error(e.getMessage(),e); + throw e; + } + } + } else { + logger.info("****pdf不存在,无法转换****"); + } + } else { + logger.info("****swf已经存在不需要转换****"); + } + }*/ + + static String loadStream(InputStream in) throws IOException { + + int ptr = 0; + in = new BufferedInputStream(in); + StringBuilder buffer = new StringBuilder(); + while ((ptr = in.read()) != -1) { + buffer.append((char) ptr); + } + + return buffer.toString(); + } + /** + * 转换主方法 + */ + @SuppressWarnings("unused") + public File conver(String fileType) { + if (ENVIRONMENT == 1) { + logger.info("****swf转换器开始工作,当前设置运行环境windows****"); + } else { + logger.info("****swf转换器开始工作,当前设置运行环境linux****"); + } + try { + if(StringUtils.isNotBlank(fileType)){ + fileType = fileType.toUpperCase(); + if(".DOC".equals(fileType) || ".DOCX".equals(fileType) || ".XLSX".equals(fileType) || ".XLS".equals(fileType) || ".PPT".equals(fileType) || ".PPTX".equals(fileType)){ + doc2pdf(); + /*pdf2swf(fileType);*/ + } else if (".PDF".equals(fileType)){ + /*pdf2swf(fileType);*/ + } + }else{ + logger.error("文件类型后缀获取失败,请检查文件名称格式是否正确"); + } + } catch (Exception e) { + logger.error(e.getMessage(),e); + return new File(""); + } + + return pdfFile; + + } + + /** + * 返回文件路径 + * + * @param + */ + public String getswfPath() { + if (swfFile.exists()) { + String tempString = swfFile.getPath(); + tempString = tempString.replaceAll("\\\\", "/"); + return tempString; + } else { + return ""; + } + + } + + public String getpdfPath() { + if (pdfFile!= null && !pdfFile.getPath().isEmpty()) { + String tempString = pdfFile.getPath(); + tempString = tempString.replaceAll("\\\\", "/"); + return tempString; + } else { + return ""; + } + + } + + /** + * 设置输出路径 + */ + public void setOutputPath(String outputPath) { + this.outputPath = outputPath; + if (!outputPath.equals("")) { + String realName = fileName.substring(fileName.lastIndexOf("/"), fileName.lastIndexOf(".")); + //TODO 此处的if判断执行的代码逻辑完全一样, 因此将其判断注释掉,直接执行 +/* if (outputPath.charAt(outputPath.length()) == '/') { + swfFile = new File(outputPath + realName + ".swf"); + } else { + swfFile = new File(outputPath + realName + ".swf"); + }*/ + swfFile = new File(outputPath + realName + ".swf"); + } + } + + public String getConvertHost() { + return convertHost; + } + + public void setConvertHost(String convertHost) { + this.convertHost = convertHost; + } +} diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java new file mode 100644 index 00000000..d9887b21 --- /dev/null +++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/DocConverterPdfOld.java @@ -0,0 +1,225 @@ +package com.adc.da.convert.common; + +import com.artofsolving.jodconverter.DocumentConverter; +import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection; +import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection; +import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +public class DocConverterPdfOld { + + private static final Logger logger = LoggerFactory.getLogger(DocConverterPdf.class); + + private static final int ENVIRONMENT = 1;// 环境 1:windows 2:linux + private String fileString;// (只涉及pdf2swf路径问题) + private String outputPath = "";// 输入路径 ,如果不设置就输出在默认的位置 + private String fileName; + private File pdfFile; + private File convertPdfFile; + private File swfFile; + private File docFile; + String waterPdfPath; + + public DocConverterPdfOld(String fileString, String fileType) { + ini(fileString,fileType); + } + + /** + * 重新设置file + * + * @param fileString + */ + public void setFile(String fileString,String fileType) { + ini(fileString,fileType); + } + + /** + * 初始化 + * + * @param fileString + */ + private void ini(String fileString,String fileType) { + this.fileString = fileString; + fileName = fileString.substring(0, fileString.lastIndexOf(".")); + if(".doc".equals(fileType) || ".docx".equals(fileType) || ".xlsx".equals(fileType) || ".xls".equals(fileType) || ".ppt".equals(fileType) || ".pptx".equals(fileType)){ + docFile = new File(fileString); + convertPdfFile=new File(fileName+"_C"+ ".pdf"); + pdfFile = new File(fileName + ".pdf"); + swfFile = new File(fileName + ".swf"); + } else if (".pdf".equals(fileType)){ + pdfFile = new File(fileName + ".pdf"); + swfFile = new File(fileName + ".swf"); + } + } + + /** + * 转为PDF + * + * @param + */ + private void doc2pdf() throws Exception { + if (!pdfFile.exists()) { + OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100); + try { + connection.connect(); + DocumentConverter converter = new OpenOfficeDocumentConverter(connection); + converter.convert(docFile, convertPdfFile); + + //addWaterToPdf(pdfFile,userId); + + // close the connection + connection.disconnect(); + // 开始设置PDF文档相关属性保证其安全性 + logger.info("开始设置转换后的PDF文件安全性相关设置"); + logger.info("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****"); + } catch (java.net.ConnectException e) { + logger.error(e.getMessage(),e); + logger.info("****pdf转换器异常,openoffice服务未启动!****"); + throw e; + } catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) { + logger.error(e.getMessage(),e); + logger.info("****pdf转换器异常,读取转换文件失败****"); + throw e; + } catch (Exception e) { + logger.error(e.getMessage(),e); + throw e; + } + } else { + logger.info("****已经转换为pdf,不需要再进行转化****"); + } + } + + /** + * 转换成 swf + */ + @SuppressWarnings("unused") + /*private void pdf2swf(String fileType) throws Exception { + Runtime r = Runtime.getRuntime(); + if (!swfFile.exists()) { + if (pdfFile.exists()) { + if (ENVIRONMENT == 1) {// windows环境处理 + try { + //String paperSwfFile = swfFile.getPath().replace(".swf","%.swf"); + Process p = r.exec("G:/swftTools/pdf2swf.exe "+ waterPdfPath + " -o "+ swfFile.getPath() + " -f -T 9 -t -s languagedir=G:/xpdf/xpdf-chinese-simplified"); + logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****"); + if(".doc".equals(fileType) || ".docx".equals(fileType)){ + *//*if (pdfFile.exists()) { + pdfFile.delete(); + }*//* + } + } catch (IOException e) { + logger.error(e.getMessage(),e); + throw e; + } + } else if (ENVIRONMENT == 2) {// linux环境处理 + try { + Process p = r.exec("pdf2swf " + pdfFile.getPath() + + " -o " + swfFile.getPath() + " -f -T 9 -t -s storeallcharacters"); + logger.info("****swf转换成功,文件输出:" + swfFile.getPath() + "****"); + if (pdfFile.exists()) { + if(!pdfFile.delete()){ + logger.error("文件删除失败!!!"); + } + } + } catch (Exception e) { + logger.error(e.getMessage(),e); + throw e; + } + } + } else { + logger.info("****pdf不存在,无法转换****"); + } + } else { + logger.info("****swf已经存在不需要转换****"); + } + }*/ + + static String loadStream(InputStream in) throws IOException { + + int ptr = 0; + in = new BufferedInputStream(in); + StringBuilder buffer = new StringBuilder(); + while ((ptr = in.read()) != -1) { + buffer.append((char) ptr); + } + + return buffer.toString(); + } + /** + * 转换主方法 + */ + @SuppressWarnings("unused") + public File conver(String fileType) { + if (ENVIRONMENT == 1) { + logger.info("****swf转换器开始工作,当前设置运行环境windows****"); + } else { + logger.info("****swf转换器开始工作,当前设置运行环境linux****"); + } + try { + if(".doc".equals(fileType) || ".docx".equals(fileType) || ".xlsx".equals(fileType) || ".xls".equals(fileType) || ".ppt".equals(fileType) || ".pptx".equals(fileType)){ + doc2pdf(); + /*pdf2swf(fileType);*/ + } else if (".pdf".equals(fileType)){ + /*pdf2swf(fileType);*/ + } + + } catch (Exception e) { + logger.error(e.getMessage(),e); + return new File(""); + } + + return pdfFile; + + } + + /** + * 返回文件路径 + * + * @param + */ + public String getswfPath() { + if (swfFile.exists()) { + String tempString = swfFile.getPath(); + tempString = tempString.replaceAll("\\\\", "/"); + return tempString; + } else { + return ""; + } + + } + + public String getpdfPath() { + if (!pdfFile.getPath().isEmpty()) { + String tempString = pdfFile.getPath(); + tempString = tempString.replaceAll("\\\\", "/"); + return tempString; + } else { + return ""; + } + + } + + /** + * 设置输出路径 + */ + public void setOutputPath(String outputPath) { + this.outputPath = outputPath; + if (!outputPath.equals("")) { + String realName = fileName.substring(fileName.lastIndexOf("/"), fileName.lastIndexOf(".")); + //TODO 此处的if判断执行的代码逻辑完全一样, 因此将其判断注释掉,直接执行 +/* if (outputPath.charAt(outputPath.length()) == '/') { + swfFile = new File(outputPath + realName + ".swf"); + } else { + swfFile = new File(outputPath + realName + ".swf"); + }*/ + swfFile = new File(outputPath + realName + ".swf"); + } + } + +} diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java new file mode 100644 index 00000000..515b6106 --- /dev/null +++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/PDFEditUtils.java @@ -0,0 +1,34 @@ +package com.adc.da.convert.common; + + +import com.itextpdf.kernel.pdf.*; + +import java.io.File; +import java.io.IOException; + +/*** + * + * @MethodName:PDF编辑工具类 + * @author: zhangyanduan + * @param: + * @return: + * date: 2019/3/6 18:36 + */ +public class PDFEditUtils { + + //设置安全性 + public static void setPDFFileSecurity(String descFilePath,String srcFilePath) throws IOException { + checkOutFile(descFilePath); + PdfReader reader = new PdfReader(srcFilePath, new ReaderProperties()); + PdfWriter writer = new PdfWriter(descFilePath, new WriterProperties() + .setStandardEncryption(null, "1234qwer".getBytes(), EncryptionConstants.ALLOW_SCREENREADERS, + EncryptionConstants.ENCRYPTION_AES_128 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA)); + PdfDocument pdfDoc = new PdfDocument(reader, writer); + pdfDoc.close(); + } + + private static void checkOutFile(String descFilePath){ + File desc=new File(descFilePath); + desc.getParentFile().mkdirs(); + } +} diff --git a/adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java b/adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java new file mode 100644 index 00000000..7160d5c5 --- /dev/null +++ b/adc-da-convert/src/main/java/com/adc/da/convert/common/SplitPdf.java @@ -0,0 +1,169 @@ +package com.adc.da.convert.common; + +import com.adc.da.util.utils.UUID; +import com.itextpdf.text.*; +import com.itextpdf.text.log.Logger; +import com.itextpdf.text.log.LoggerFactory; +import com.itextpdf.text.pdf.*; +import org.apache.commons.lang.StringUtils; +import sun.misc.BASE64Encoder; + +import java.io.*; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class SplitPdf { + + private static final Logger logger = LoggerFactory.getLogger(SplitPdf.class); + + public static String splitPDFFile(String inputPath, + String outputPath, int fromPage, int toPage) { + Document document = new Document(); + InputStream inputStream = null; + OutputStream outputStream = null; + String allPassword = ""; + try { + logger.info("*********开始拆分pdf**********"); + inputStream = new FileInputStream(inputPath); + outputStream = new FileOutputStream(outputPath); + PdfReader inputPDF = new PdfReader(inputStream); + int totalPages = inputPDF.getNumberOfPages(); + //make fromPage equals to toPage if it is greater + if(fromPage > toPage ) { + fromPage = toPage; + } + if(toPage > totalPages) { + toPage = totalPages; + } + + // Create a writer for the outputstream + PdfWriter writer = PdfWriter.getInstance(document, outputStream); + Map pwdMap = setFilePassword(); + allPassword = pwdMap.get("allPwd"); + String filepassword = pwdMap.get("filePwd"); + writer.setEncryption(filepassword.getBytes(), "1234qwer".getBytes(), + PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128); + document.open(); + //构造文件,防止初始化文件为空 + //document.add(new Chunk("")); + PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data + PdfImportedPage page; + + while(fromPage <= toPage) { + Rectangle pageSize = inputPDF.getPageSize(fromPage); + document.setPageSize(new Rectangle(pageSize.getWidth(),pageSize.getHeight())); + document.newPage(); + page = writer.getImportedPage(inputPDF, fromPage); + // 此处将文档的旋转参数写入新的文档中 + /* PdfDictionary pageN = inputPDF.getPageN(fromPage); + PdfNumber asNumber = pageN.getAsNumber(PdfName.ROTATE); + PdfDictionary additional = new PdfDictionary(); + additional.put(PdfName.ROTATE,asNumber); + page.setAdditional(additional);*/ + cb.addTemplate(page, 0, 0); + fromPage++; + } + outputStream.flush(); + document.close(); + inputStream.close(); + outputStream.close(); + //加密码 + /*String path = outputPath.replace("测试文件拆分\\","测试文件拆分\\加密码\\"); + PDFEditUtils.setPDFFileSecurity(outputPath,outputPath);*/ + }catch (IllegalArgumentException ie){ + logger.error("拆分过程中,读取文件失败"); + logger.error(ie.getMessage(),ie); + logger.error(ie.getMessage()); + } catch (IOException ioe) { + logger.error("拆分过程中,读取文件IO失败"); + logger.error(ioe.getMessage(),ioe); + logger.error(ioe.getMessage()); + }catch (Exception e) { + logger.error(e.getMessage(),e); + logger.error(e.getMessage()); + } finally { + if(document.isOpen()){ + document.close(); + } + try { + if (inputStream != null){ + inputStream.close(); + } + if (outputStream != null){ + outputStream.close(); + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + return allPassword; + } + + /** + * 利用libreOffice将office文档转换成pdf + * @param inputFile 目标文件地址 + * @param pdfFile 输出文件夹 + * @return + */ + public static boolean convertOffice2PDF(String inputFile, String pdfFile){ + long start = System.currentTimeMillis(); + String command; + boolean flag; + String osName = System.getProperty("os.name"); + if (osName.contains("Windows")) { + command = "cmd /c soffice --headless --invisible --convert-to pdf:writer_pdf_Export " + inputFile + " --outdir " + pdfFile; + }else { + command = "libreoffice --headless --invisible --convert-to pdf:writer_pdf_Export " + inputFile + " --outdir " + pdfFile; + } + flag = executeLibreOfficeCommand(command); + long end = System.currentTimeMillis(); + logger.debug("用时:{} ms"+(end - start)); + return flag; + } + + + /** + * 执行command指令 + * @param command + * @return + */ + public static boolean executeLibreOfficeCommand(String command) { + logger.info("开始进行转化......."); + Process process;// Process可以控制该子进程的执行或获取该子进程的信息 + try { + logger.info("convertOffice2PDF cmd : {}"+ command); + process = Runtime.getRuntime().exec(command);// exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。 + // 下面两个可以获取输入输出流 +// InputStream errorStream = process.getErrorStream(); +// InputStream inputStream = process.getInputStream(); + } catch (IOException e) { + logger.error(" convertOffice2PDF {} error"+command, e); + return false; + } + int exitStatus = 0; + try { + exitStatus = process.waitFor();// 等待子进程完成再往下执行,返回值是子线程执行完毕的返回值,返回0表示正常结束 + // 第二种接受返回值的方法 + int i = process.exitValue(); // 接收执行完毕的返回值 + logger.debug("返回值:"+i); + } catch (InterruptedException e) { + logger.info("InterruptedException convertOffice2PDF {}"+ command); + return false; + } + logger.info("convertOffice2PDF cmd exitStatus {}"+ exitStatus); + process.destroy(); // 销毁子进程 + logger.info("转化结束......."); + return true; + } + //设置文件密码 + public static Map setFilePassword(){ + String allPwd = UUID.randomUUID(20); + String filePwd = allPwd.substring(0,5) + allPwd.substring(15,20); + Map map = new HashMap<>(); + map.put("allPwd",allPwd); + map.put("filePwd",filePwd); + return map; + } + +} diff --git a/adc-da-convert/src/main/lib/jodconverter-2.2.2.jar b/adc-da-convert/src/main/lib/jodconverter-2.2.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..d033256e8245d18c4340b5559a8a75a8ee7bc349 GIT binary patch literal 32054 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 F{vXwFhfn|j literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index ca9ad0c4..4cec972f 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,8 @@ adc-da-search adc-da-slrs adc-da-activiti - + adc-da-convert +