实现使用jodconverter调用libreoffice将word转pdf
This commit is contained in:
11
README.md
11
README.md
@@ -2,8 +2,13 @@
|
|||||||
|
|
||||||
文书服务
|
文书服务
|
||||||
|
|
||||||
api下为调用的接口,在需要处理文书的项目中引用,以`fegin方式`配置Service后进行调用
|
+ api下为调用的接口,在需要处理文书的项目中引用,以`Http Invoker`配置Service后进行调用
|
||||||
|
+ 参考[在Spring Boot中使用Http Invoker](https://codeleading.com/article/15413828287/) 的`Client`部分
|
||||||
|
|
||||||
server下为使用jacob处理word文书,使用openoffice来进行pdf转换,`java -jar xxx.jar`启动
|
+ [jod-document-server](document-server/jod-document-server)下使用poi-tl处理word文件,使用jacob处理调用[LibreOffice](https://zh-cn.libreoffice.org/)来进行格式转换,`java -jar xxx.jar`启动
|
||||||
|
+ 参考:[springboot整合libreoffice(两种方式,使用本地和远程的libreoffice);docker中同时部署应用和libreoffice](https://blog.csdn.net/qq_42882229/article/details/140917550)
|
||||||
|
+ 在Linux下,需要注意word文件的字体,必须在Linux中存在
|
||||||
|
+ 若出现格式问题,需先使用LibreOffice打开修复后,在进行转换
|
||||||
|
|
||||||
tl-server下仅进行word转pdf,使用的docto调用office来转换,`java -jar xxx.jar`启动
|
+ [docto-document-server](document-server/docto-document-server)下使用poi-tl处理word文件,使用docto调用`Microsoft Office`来转换格式,`java -jar xxx.jar`启动
|
||||||
|
+ 仅能运行在Windows,兼容性最好,比较慢
|
||||||
33
api/pom.xml
33
api/pom.xml
@@ -1,33 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.optima</groupId>
|
|
||||||
<artifactId>document-api</artifactId>
|
|
||||||
<version>2.0.0</version>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<source>8</source>
|
|
||||||
<target>8</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<name>document api</name>
|
|
||||||
<description>文档操作api</description>
|
|
||||||
<properties>
|
|
||||||
<java.version>1.8</java.version>
|
|
||||||
</properties>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.16.20</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package com.optima.document.api;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文档接口,此类中用的jacob生成word文档,插入图片等,使用openoffice进行格式转换
|
|
||||||
*
|
|
||||||
* @author Elias
|
|
||||||
* @since 2021-09-28 16:00
|
|
||||||
*/
|
|
||||||
public interface LegacyDocumentService extends BaseDocumentService {
|
|
||||||
/**
|
|
||||||
* 通过jacob向文档中插入图片,仅server模块下实现
|
|
||||||
*
|
|
||||||
* @param source 文档流
|
|
||||||
* @param toFindText 需要替换的文本
|
|
||||||
* @param imgSource 图片流
|
|
||||||
* @param width 宽度
|
|
||||||
* @param height 高度
|
|
||||||
* @return word文档流
|
|
||||||
*/
|
|
||||||
default byte[] insertJpeg(byte[] source, String toFindText, byte[] imgSource, int width, int height) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过jacob向文档中插入多张图片,仅server模块下实现
|
|
||||||
*
|
|
||||||
* @param source 文档流
|
|
||||||
* @param toFindText 需要替换的文本
|
|
||||||
* @param imgSource 图片流列表
|
|
||||||
* @param width 宽度
|
|
||||||
* @param height 高度
|
|
||||||
* @return word文档流
|
|
||||||
*/
|
|
||||||
default byte[] insertJpeg(byte[] source, String toFindText, List<byte[]> imgSource, int width, int height) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过jacob向word填充属性字段,仅server模块下实现
|
|
||||||
*
|
|
||||||
* @param source 文档流
|
|
||||||
* @param infoMap 字段集合,${key}为占位字符,value为对应替换内容
|
|
||||||
* @return word文档流
|
|
||||||
*/
|
|
||||||
default byte[] fieldToWord(byte[] source, Map<String, Object> infoMap) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
58
document-api/pom.xml
Normal file
58
document-api/pom.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.optima</groupId>
|
||||||
|
<artifactId>document</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>document-api</artifactId>
|
||||||
|
<name>Document API</name>
|
||||||
|
<description>文档操作api</description>
|
||||||
|
<properties>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.16.20</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- 1. 使用 maven-jar-plugin 打包当前模块的代码(不含依赖) -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
<configuration>
|
||||||
|
<!-- 可选:指定主类(如果需要可执行) -->
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>com.example.MyApp</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- 2. 使用 maven-source-plugin 生成源码 JAR -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -1,17 +1,34 @@
|
|||||||
package com.optima.document.api;
|
package com.optima.document.api;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanghuanglin
|
* @author yanghuanglin
|
||||||
* @since 2022/12/28
|
* @since 2022/12/28
|
||||||
*/
|
*/
|
||||||
public interface BaseDocumentService {
|
public interface BaseDocumentService {
|
||||||
/**
|
/**
|
||||||
* 格式转换,server和tl-server下均实现
|
* 格式转换
|
||||||
*
|
*
|
||||||
* @param source 源文件流,tl-server下仅支持docx格式
|
* @param source 源文件流,仅支持docx格式
|
||||||
* @param sourceExtension 源文件后缀名,不包含"."
|
* @param sourceExtension 源文件后缀名,不包含"."
|
||||||
* @param targetExtension 目标文件后缀名,不包含"."
|
* @param targetExtension 目标文件后缀名,不包含"."
|
||||||
* @param targetFormat 目标文件格式,需与目标文件后缀名匹配,server下此参数无效。,tl-server下参考: <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.word.wdsaveformat">word格式</a>
|
* @return 转换后的文件流
|
||||||
|
*/
|
||||||
|
default byte[] convert(byte[] source, String sourceExtension, String targetExtension) {
|
||||||
|
return convert(source, sourceExtension, targetExtension, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式转换
|
||||||
|
*
|
||||||
|
* @param source 源文件流,仅支持docx格式
|
||||||
|
* @param sourceExtension 源文件后缀名,不包含"."
|
||||||
|
* @param targetExtension 目标文件后缀名,不包含"."
|
||||||
|
* @param targetFormat 目标文件格式,需与目标文件后缀名匹配。
|
||||||
|
* server下此参数无效。
|
||||||
|
* tl-server下参考:
|
||||||
|
* <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.word.wdsaveformat">word格式</a>
|
||||||
* 或 <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel.xlfileformat">excel格式</a>
|
* 或 <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel.xlfileformat">excel格式</a>
|
||||||
* 或 <a href="https://docs.microsoft.com/en-us/office/vba/api/powerpoint.presentation.saveas">powerpoint格式</a>
|
* 或 <a href="https://docs.microsoft.com/en-us/office/vba/api/powerpoint.presentation.saveas">powerpoint格式</a>
|
||||||
* @return 转换后的文件流
|
* @return 转换后的文件流
|
||||||
@@ -21,9 +38,20 @@ public interface BaseDocumentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* word转为pdf,server和tl-server下均实现
|
* 通过调用poi生成word
|
||||||
*
|
*
|
||||||
* @param source word文件流,tl-server下仅支持docx格式
|
* @param sourceTemplate word模版流,仅支持docx格式
|
||||||
|
* @param dataModel 数据模型
|
||||||
|
* @return word文档流
|
||||||
|
*/
|
||||||
|
default byte[] generateWord(byte[] sourceTemplate, Map<String, Object> dataModel) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* word转为pdf
|
||||||
|
*
|
||||||
|
* @param source word文件流,仅支持docx格式
|
||||||
* @param sourceFormat 源文件后缀名,不包含".",tl-server下此参数无效
|
* @param sourceFormat 源文件后缀名,不包含".",tl-server下此参数无效
|
||||||
* @param clear 是否清除占位符,如果为true,则在tl-server下源文件只支持docx格式
|
* @param clear 是否清除占位符,如果为true,则在tl-server下源文件只支持docx格式
|
||||||
* @return pdf文档流
|
* @return pdf文档流
|
||||||
@@ -35,7 +63,7 @@ public interface BaseDocumentService {
|
|||||||
/**
|
/**
|
||||||
* 通过pdfbox将word转图片
|
* 通过pdfbox将word转图片
|
||||||
*
|
*
|
||||||
* @param source word文件流,tl-server下仅支持docx格式
|
* @param source word文件流,仅支持docx格式
|
||||||
* @param sourceExtension 源文件后缀名,不包含".",server下此参数无效
|
* @param sourceExtension 源文件后缀名,不包含".",server下此参数无效
|
||||||
* @param targetExtension 目标格式 支持jpeg, jpg, gif, tiff or png
|
* @param targetExtension 目标格式 支持jpeg, jpg, gif, tiff or png
|
||||||
* @return 图片流
|
* @return 图片流
|
||||||
@@ -45,7 +73,7 @@ public interface BaseDocumentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* doc转为docx,server和tl-server下均实现
|
* doc转为docx
|
||||||
*
|
*
|
||||||
* @param source doc文档流
|
* @param source doc文档流
|
||||||
* @return docx文档流
|
* @return docx文档流
|
||||||
@@ -55,7 +83,7 @@ public interface BaseDocumentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xls转为xlsx,server和tl-server下均实现
|
* xls转为xlsx
|
||||||
*
|
*
|
||||||
* @param source xls文档流
|
* @param source xls文档流
|
||||||
* @return xlsx文档流
|
* @return xlsx文档流
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.optima.document.api;
|
package com.optima.document.api;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文档接口,此类中用的poi2生成word文档,使用docto进行格式转换
|
* 文档接口,此类中用的poi2生成word文档,使用docto进行格式转换
|
||||||
*
|
*
|
||||||
@@ -10,18 +8,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public interface DocumentService extends BaseDocumentService {
|
public interface DocumentService extends BaseDocumentService {
|
||||||
/**
|
/**
|
||||||
* 通过调用poi生成word,仅tl-server模块下实现,仅支持docx格式
|
* 通过调用poi将word转pdf,如果clear为true,则仅支持docx格式
|
||||||
*
|
|
||||||
* @param sourceTemplate word模版流,仅支持docx格式
|
|
||||||
* @param dataModel 数据模型
|
|
||||||
* @return word文档流
|
|
||||||
*/
|
|
||||||
default byte[] generateWord(byte[] sourceTemplate, Map<String, Object> dataModel) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过调用poi将word转pdf,仅tl-server模块下实现,如果clear为true,则仅支持docx格式
|
|
||||||
*
|
*
|
||||||
* @param source word模版流,仅支持docx格式
|
* @param source word模版流,仅支持docx格式
|
||||||
* @param clear 是否清除占位符
|
* @param clear 是否清除占位符
|
||||||
20
document-server/docto-document-server/pom.xml
Normal file
20
document-server/docto-document-server/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.optima</groupId>
|
||||||
|
<artifactId>document-server</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>docto-document-server</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
<name>Docto Document server</name>
|
||||||
|
<description>Docto 文档操作服务</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
package com.optima.document.tl.server;
|
package com.optima.document.server;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class DocumentServer {
|
public class DoctoDocumentServer {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(DocumentServer.class, args);
|
SpringApplication.run(DoctoDocumentServer.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.optima.document.tl.server.api;
|
package com.optima.document.server.api;
|
||||||
|
|
||||||
import com.deepoove.poi.XWPFTemplate;
|
import com.deepoove.poi.XWPFTemplate;
|
||||||
import com.deepoove.poi.config.Configure;
|
import com.deepoove.poi.config.Configure;
|
||||||
@@ -11,7 +11,7 @@ import com.deepoove.poi.template.run.RunTemplate;
|
|||||||
import com.deepoove.poi.xwpf.BodyContainer;
|
import com.deepoove.poi.xwpf.BodyContainer;
|
||||||
import com.deepoove.poi.xwpf.BodyContainerFactory;
|
import com.deepoove.poi.xwpf.BodyContainerFactory;
|
||||||
import com.optima.document.api.DocumentService;
|
import com.optima.document.api.DocumentService;
|
||||||
import com.optima.document.tl.server.config.DocumentConfig;
|
import com.optima.document.server.config.DocumentConfig;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.rendering.ImageType;
|
import org.apache.pdfbox.rendering.ImageType;
|
||||||
@@ -42,11 +42,13 @@ import java.util.UUID;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class DocumentServiceImpl implements DocumentService {
|
public class DocumentServiceImpl implements DocumentService {
|
||||||
|
@Resource
|
||||||
|
private DocumentConfig documentConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* word模版引擎配置
|
* word模版引擎配置
|
||||||
*/
|
*/
|
||||||
private static final Configure wtlConfig = Configure.builder().buildGramer("${", "}")
|
Configure wtlConfig = Configure.builder().buildGramer("${", "}")
|
||||||
.setValidErrorHandler(new Configure.DiscardHandler())
|
.setValidErrorHandler(new Configure.DiscardHandler())
|
||||||
.addPlugin('%', new ListRenderPolicy() {
|
.addPlugin('%', new ListRenderPolicy() {
|
||||||
@Override
|
@Override
|
||||||
@@ -84,9 +86,6 @@ public class DocumentServiceImpl implements DocumentService {
|
|||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DocumentConfig documentConfig;
|
|
||||||
|
|
||||||
public byte[] convert(byte[] source, String sourceExtension, String targetExtension, String targetFormat) {
|
public byte[] convert(byte[] source, String sourceExtension, String targetExtension, String targetFormat) {
|
||||||
try {
|
try {
|
||||||
sourceExtension = sourceExtension.replace(".", "");
|
sourceExtension = sourceExtension.replace(".", "");
|
||||||
@@ -108,17 +107,17 @@ public class DocumentServiceImpl implements DocumentService {
|
|||||||
Process p = Runtime.getRuntime().exec(command);
|
Process p = Runtime.getRuntime().exec(command);
|
||||||
p.waitFor();
|
p.waitFor();
|
||||||
long end = System.currentTimeMillis();
|
long end = System.currentTimeMillis();
|
||||||
log.info("docto convert {} to {} take time in millis:{}", sourceExtension, targetExtension, (end - begin));
|
log.info("convert {} to {} take time in millis:{}", sourceExtension, targetExtension, (end - begin));
|
||||||
return Files.readAllBytes(targetPath);
|
return Files.readAllBytes(targetPath);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
log.error("convert {} to {} error", sourceExtension, targetExtension, e);
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
Files.delete(sourcePath);
|
Files.delete(sourcePath);
|
||||||
Files.delete(targetPath);
|
Files.delete(targetPath);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("docto convert error", e);
|
log.error("convert error", e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -155,9 +154,9 @@ public class DocumentServiceImpl implements DocumentService {
|
|||||||
});
|
});
|
||||||
template.writeAndClose(bos);
|
template.writeAndClose(bos);
|
||||||
source = bos.toByteArray();
|
source = bos.toByteArray();
|
||||||
log.info("清空占位符=======耗时:{} 毫秒", System.currentTimeMillis() - start);
|
log.info("clear placeholder take time in millis:{}", System.currentTimeMillis() - start);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("清空标签失败:", e);
|
log.error("clear placeholder error", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.optima.document.tl.server.config;
|
package com.optima.document.server.config;
|
||||||
|
|
||||||
import com.optima.document.api.DocumentService;
|
import com.optima.document.api.DocumentService;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -13,7 +13,7 @@ import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
|
|||||||
* @author Elias
|
* @author Elias
|
||||||
* @since 2021-09-28 16:12
|
* @since 2021-09-28 16:12
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("VulnerableCodeUsages")
|
@SuppressWarnings("deprecation")
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "document")
|
@ConfigurationProperties(prefix = "document")
|
||||||
@Data
|
@Data
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
server:
|
||||||
|
port: 9004
|
||||||
|
|
||||||
|
document:
|
||||||
|
doc-to-program: C:\\DocumentServer\\docto.exe
|
||||||
32
document-server/jod-document-server/pom.xml
Normal file
32
document-server/jod-document-server/pom.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.optima</groupId>
|
||||||
|
<artifactId>document-server</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>jod-document-server</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
<name>Jod Document Server</name>
|
||||||
|
<description>Jod 文档操作服务</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jodconverter.version>4.4.9</jodconverter.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jodconverter</groupId>
|
||||||
|
<artifactId>jodconverter-local</artifactId>
|
||||||
|
<version>${jodconverter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jodconverter</groupId>
|
||||||
|
<artifactId>jodconverter-spring-boot-starter</artifactId>
|
||||||
|
<version>${jodconverter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -4,10 +4,10 @@ import org.springframework.boot.SpringApplication;
|
|||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class DocumentServer {
|
public class JodDocumentServer {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(DocumentServer.class, args);
|
SpringApplication.run(JodDocumentServer.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
package com.optima.document.server.api;
|
||||||
|
|
||||||
|
import com.deepoove.poi.XWPFTemplate;
|
||||||
|
import com.deepoove.poi.config.Configure;
|
||||||
|
import com.deepoove.poi.data.PictureRenderData;
|
||||||
|
import com.deepoove.poi.data.TextRenderData;
|
||||||
|
import com.deepoove.poi.policy.ListRenderPolicy;
|
||||||
|
import com.deepoove.poi.policy.PictureRenderPolicy;
|
||||||
|
import com.deepoove.poi.render.RenderContext;
|
||||||
|
import com.deepoove.poi.template.run.RunTemplate;
|
||||||
|
import com.deepoove.poi.xwpf.BodyContainer;
|
||||||
|
import com.deepoove.poi.xwpf.BodyContainerFactory;
|
||||||
|
import com.optima.document.api.DocumentService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.rendering.ImageType;
|
||||||
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||||
|
import org.apache.pdfbox.tools.imageio.ImageIOUtil;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFRun;
|
||||||
|
import org.jodconverter.core.DocumentConverter;
|
||||||
|
import org.jodconverter.core.document.DefaultDocumentFormatRegistry;
|
||||||
|
import org.jodconverter.core.document.DocumentFormat;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务接口实现
|
||||||
|
*
|
||||||
|
* @author Elias
|
||||||
|
* @since 2021-09-28 16:18
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DocumentServiceImpl implements DocumentService {
|
||||||
|
@Resource
|
||||||
|
private DocumentConverter documentConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* word模版引擎配置
|
||||||
|
*/
|
||||||
|
private static final Configure wtlConfig = Configure.builder().buildGramer("${", "}")
|
||||||
|
.setValidErrorHandler(new Configure.DiscardHandler())
|
||||||
|
.addPlugin('%', new ListRenderPolicy() {
|
||||||
|
@Override
|
||||||
|
public void doRender(RenderContext<List<Object>> context) throws Exception {
|
||||||
|
XWPFRun run = context.getRun();
|
||||||
|
List<?> dataList = context.getData();
|
||||||
|
Iterator<?> var5 = dataList.iterator();
|
||||||
|
while (var5.hasNext()) {
|
||||||
|
Object data = var5.next();
|
||||||
|
if (data instanceof TextRenderData) {
|
||||||
|
run.setText(((TextRenderData) data).getText());
|
||||||
|
if (var5.hasNext()) {
|
||||||
|
run.setText(",");
|
||||||
|
}
|
||||||
|
} else if (data instanceof PictureRenderData) {
|
||||||
|
PictureRenderPolicy.Helper.renderPicture(run, (PictureRenderData) data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.setRenderDataComputeFactory(envModel ->
|
||||||
|
el -> {
|
||||||
|
Object data = envModel.getRoot();
|
||||||
|
if ("#this".equals(el)) {
|
||||||
|
return data;
|
||||||
|
} else if (data instanceof Map) {
|
||||||
|
Map dataMap = ((Map) data);
|
||||||
|
if (dataMap.containsKey(el)) {
|
||||||
|
return dataMap.get(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件格式转换
|
||||||
|
*
|
||||||
|
* @param source 源文件流
|
||||||
|
* @param sourceExtension 源文件后缀名,不包含"."
|
||||||
|
* @param targetExtension 目标文件后缀名
|
||||||
|
* @return 转换后的文件流
|
||||||
|
*/
|
||||||
|
public byte[] convert(byte[] source, String sourceExtension, String targetExtension) {
|
||||||
|
try {
|
||||||
|
sourceExtension = sourceExtension.replace(".", "");
|
||||||
|
targetExtension = targetExtension.replace(".", "");
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
DocumentFormat sourceFormat = DefaultDocumentFormatRegistry.getFormatByExtension(sourceExtension);
|
||||||
|
DocumentFormat targetFormat = DefaultDocumentFormatRegistry.getFormatByExtension(targetExtension);
|
||||||
|
assert sourceFormat != null;
|
||||||
|
assert targetFormat != null;
|
||||||
|
documentConverter.convert(new ByteArrayInputStream(source))
|
||||||
|
.as(sourceFormat)
|
||||||
|
.to(bos)
|
||||||
|
.as(targetFormat)
|
||||||
|
.execute();
|
||||||
|
log.info("convert {} to {} take time in millis:{}", sourceExtension, targetExtension, System.currentTimeMillis() - start);
|
||||||
|
return bos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("convert {} to {} error", sourceExtension, targetExtension, e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] convert(byte[] source, String sourceExtension, String targetExtension, String targetFormat) {
|
||||||
|
return convert(source, sourceExtension, targetExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] generateWord(byte[] sourceTemplate, Map<String, Object> dataModel) {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
XWPFTemplate template = XWPFTemplate.compile(new ByteArrayInputStream(sourceTemplate), wtlConfig).render(dataModel);
|
||||||
|
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||||
|
template.write(bos);
|
||||||
|
log.info("word generate take time in millis:{}", System.currentTimeMillis() - start);
|
||||||
|
return bos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("word generate error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] wordToPdf(byte[] source, String sourceFormat, boolean clear) {
|
||||||
|
return wordToPdf(source, clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] wordToPdf(byte[] source, boolean clear) {
|
||||||
|
try {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
if (clear) {
|
||||||
|
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||||
|
XWPFTemplate template = XWPFTemplate.compile(new ByteArrayInputStream(source), wtlConfig);
|
||||||
|
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(template.getXWPFDocument());
|
||||||
|
template.getElementTemplates().forEach(it -> {
|
||||||
|
if (it instanceof RunTemplate) {
|
||||||
|
RunTemplate rt = (RunTemplate) it;
|
||||||
|
bodyContainer.clearPlaceholder(rt.getRun());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
template.writeAndClose(bos);
|
||||||
|
source = bos.toByteArray();
|
||||||
|
log.info("clear placeholder take time in millis:{}", System.currentTimeMillis() - start);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("clear placeholder error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return convert(source, "docx", "pdf");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("word to pdf error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] wordToImage(byte[] source, String targetExtension) {
|
||||||
|
try {
|
||||||
|
byte[] pdfBytes = wordToPdf(source, true);
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
PDDocument document = PDDocument.load(new ByteArrayInputStream(pdfBytes));
|
||||||
|
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||||
|
BufferedImage bim = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
ImageIOUtil.writeImage(bim, targetExtension, bos, 300);
|
||||||
|
document.close();
|
||||||
|
log.info("word to image take time in millis:{}", System.currentTimeMillis() - start);
|
||||||
|
return bos.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("word to image error", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] wordToImage(byte[] source, String sourceExtension, String targetExtension) {
|
||||||
|
return wordToImage(source, targetExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] docToDocx(byte[] source) {
|
||||||
|
return convert(source, "doc", "docx");
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] xlsToXlsx(byte[] source) {
|
||||||
|
return convert(source, "xls", "xlsx");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.optima.document.server.config;
|
package com.optima.document.server.config;
|
||||||
|
|
||||||
import com.optima.document.api.LegacyDocumentService;
|
import com.optima.document.api.DocumentService;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -13,26 +13,21 @@ import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
|
|||||||
* @author Elias
|
* @author Elias
|
||||||
* @since 2021-09-28 16:12
|
* @since 2021-09-28 16:12
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("VulnerableCodeUsages")
|
@SuppressWarnings("deprecation")
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "document")
|
@ConfigurationProperties(prefix = "document")
|
||||||
@Data
|
@Data
|
||||||
public class DocumentConfig {
|
public class DocumentConfig {
|
||||||
|
|
||||||
private String tempDir;
|
|
||||||
|
|
||||||
private String openOfficeHome;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文档接口
|
* 文档接口
|
||||||
*
|
*
|
||||||
* @return httpinvoker
|
* @return httpinvoker
|
||||||
*/
|
*/
|
||||||
@Bean(name = "/document-service")
|
@Bean(name = "/document-service")
|
||||||
HttpInvokerServiceExporter wordService(LegacyDocumentService legacyDocumentService) {
|
HttpInvokerServiceExporter wordService(DocumentService documentService) {
|
||||||
HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
|
HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
|
||||||
exporter.setService(legacyDocumentService);
|
exporter.setService(documentService);
|
||||||
exporter.setServiceInterface(LegacyDocumentService.class);
|
exporter.setServiceInterface(DocumentService.class);
|
||||||
return exporter;
|
return exporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
server:
|
||||||
|
port: 9005
|
||||||
|
|
||||||
|
jodconverter:
|
||||||
|
local:
|
||||||
|
# 启动本地转换
|
||||||
|
enabled: true
|
||||||
|
# macOS下:program/soffice 的 program 所在目录 或 MacOS/soffice 的 MacOS 所在目录
|
||||||
|
# windows下:program/soffice.exe 的 program 所在目录
|
||||||
|
# linux下:program/soffice.bin 的 program 所在目录
|
||||||
|
# 如果不配置,则自动查找
|
||||||
|
office-home: /Applications/LibreOffice.app/Contents
|
||||||
|
# 一个端口表示一个常驻进程,默认只有一个进程,端口为2002
|
||||||
|
port-numbers: [ 2002 ]
|
||||||
|
# 每个进程最多处理多个任务,默认为200
|
||||||
|
max-tasks-per-process: 200
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.optima.document.server;
|
||||||
|
|
||||||
|
import com.optima.document.api.DocumentService;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Disabled
|
||||||
|
public class JodDocumentServerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() throws IOException {
|
||||||
|
DocumentService documentService = buildDocumentService();
|
||||||
|
|
||||||
|
File sourceDocx = new File("/Users/yanghuanglin/Downloads/test.docx");
|
||||||
|
File targetPdf = new File("/Users/yanghuanglin/Downloads/test.pdf");
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("callerName", "张三");
|
||||||
|
byte[] sourceBytes = documentService.generateWord(Files.readAllBytes(sourceDocx.toPath()), params);
|
||||||
|
|
||||||
|
byte[] bytes = documentService.wordToPdf(sourceBytes, false);
|
||||||
|
FileUtils.writeByteArrayToFile(targetPdf, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DocumentService buildDocumentService() {
|
||||||
|
// 创建客户端代理
|
||||||
|
HttpInvokerProxyFactoryBean factoryBean = new HttpInvokerProxyFactoryBean();
|
||||||
|
factoryBean.setServiceUrl("http://10.211.55.13:9005/document-service");
|
||||||
|
factoryBean.setServiceInterface(DocumentService.class);
|
||||||
|
factoryBean.afterPropertiesSet();
|
||||||
|
|
||||||
|
return (DocumentService) factoryBean.getObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
163
document-server/pom.xml
Normal file
163
document-server/pom.xml
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.optima</groupId>
|
||||||
|
<artifactId>document</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>document-server</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>Document Server</name>
|
||||||
|
<description>文档操作模块</description>
|
||||||
|
<modules>
|
||||||
|
<module>docto-document-server</module>
|
||||||
|
<module>jod-document-server</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<pdfbox-tools.version>2.0.25</pdfbox-tools.version>
|
||||||
|
<log4j.version>2.17.2</log4j.version>
|
||||||
|
<lombok.version>1.16.20</lombok.version>
|
||||||
|
<poi-tl.version>1.12.1</poi-tl.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.optima</groupId>
|
||||||
|
<artifactId>document-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
|
<artifactId>pdfbox-tools</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.deepoove</groupId>
|
||||||
|
<artifactId>poi-tl</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-to-slf4j</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<version>2.7.18</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
<version>2.7.18</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<version>2.7.18</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.optima</groupId>
|
||||||
|
<artifactId>document-api</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
|
<artifactId>pdfbox-tools</artifactId>
|
||||||
|
<version>${pdfbox-tools.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.deepoove</groupId>
|
||||||
|
<artifactId>poi-tl</artifactId>
|
||||||
|
<version>${poi-tl.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-to-slf4j</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<version>${log4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>document-server-${version}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-resources</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-resources</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<includes>
|
||||||
|
<include>application.yml</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
32
pom.xml
32
pom.xml
@@ -6,11 +6,35 @@
|
|||||||
<artifactId>document</artifactId>
|
<artifactId>document</artifactId>
|
||||||
<version>2.0.0</version>
|
<version>2.0.0</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>document</name>
|
<name>Document</name>
|
||||||
<description>文档操作模块</description>
|
<description>文档操作模块</description>
|
||||||
<modules>
|
<modules>
|
||||||
<module>api</module>
|
<module>document-api</module>
|
||||||
<module>server</module>
|
<module>document-server</module>
|
||||||
<module>tl-server</module>
|
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>8</source>
|
||||||
|
<target>8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>2.7.18</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
136
server/pom.xml
136
server/pom.xml
@@ -1,136 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>2.0.3.RELEASE</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>com.optima</groupId>
|
|
||||||
<artifactId>document-server</artifactId>
|
|
||||||
<version>2.0.0</version>
|
|
||||||
<name>document server</name>
|
|
||||||
<description>文档操作服务</description>
|
|
||||||
<properties>
|
|
||||||
<java.version>1.8</java.version>
|
|
||||||
<tomcat.version>8.5.100</tomcat.version>
|
|
||||||
</properties>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.optima</groupId>
|
|
||||||
<artifactId>document-api</artifactId>
|
|
||||||
<version>2.0.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
<version>3.3.2</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- jacob -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.sf.jacob-project</groupId>
|
|
||||||
<artifactId>jacob</artifactId>
|
|
||||||
<version>1.18</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${basedir}/src/main/resources/libs/jacob.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.artofsolving</groupId>
|
|
||||||
<artifactId>jodconverter</artifactId>
|
|
||||||
<version>2.2.2</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${basedir}/src/main/resources/libs/jodconverter-2.2.2.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<!-- poi2 依赖 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>apache</groupId>
|
|
||||||
<artifactId>poi2</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${basedir}/src/main/resources/libs/poi2-1.0.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<!-- poi依赖 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.poi</groupId>
|
|
||||||
<artifactId>poi</artifactId>
|
|
||||||
<version>3.14</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.poi</groupId>
|
|
||||||
<artifactId>poi-ooxml</artifactId>
|
|
||||||
<version>3.14</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.poi</groupId>
|
|
||||||
<artifactId>poi-scratchpad</artifactId>
|
|
||||||
<version>3.14</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>joda-time</groupId>
|
|
||||||
<artifactId>joda-time</artifactId>
|
|
||||||
<version>2.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.16.20</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jodconverter</groupId>
|
|
||||||
<artifactId>jodconverter-core</artifactId>
|
|
||||||
<version>4.0.0-RELEASE</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>json</artifactId>
|
|
||||||
<groupId>org.json</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<version>1.3.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.pdfbox</groupId>
|
|
||||||
<artifactId>pdfbox-tools</artifactId>
|
|
||||||
<version>2.0.25</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<includeSystemScope>true</includeSystemScope>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
package com.optima.document.server.api;
|
|
||||||
|
|
||||||
import com.artofsolving.jodconverter.DefaultDocumentFormatRegistry;
|
|
||||||
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.optima.document.api.LegacyDocumentService;
|
|
||||||
import com.optima.document.server.config.DocumentConfig;
|
|
||||||
import com.optima.document.server.utils.DocToPdfUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
||||||
import org.apache.pdfbox.rendering.ImageType;
|
|
||||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
|
||||||
import org.apache.pdfbox.tools.imageio.ImageIOUtil;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务接口实现
|
|
||||||
*
|
|
||||||
* @author Elias
|
|
||||||
* @since 2021-09-28 16:18
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class LegacyDocumentServiceImpl implements LegacyDocumentService {
|
|
||||||
@Resource
|
|
||||||
private DocumentConfig documentConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件格式转换
|
|
||||||
*
|
|
||||||
* @param source 源文件流
|
|
||||||
* @param sourceExtension 源文件后缀名,不包含"."
|
|
||||||
* @param targetExtension 目标文件后缀名
|
|
||||||
* @return 转换后的文件流
|
|
||||||
*/
|
|
||||||
private byte[] convert(byte[] source, String sourceExtension, String targetExtension) {
|
|
||||||
try {
|
|
||||||
sourceExtension = sourceExtension.replace(".","");
|
|
||||||
targetExtension = targetExtension.replace(".","");
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
String command = "%s -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\" -nofirststartwizard";
|
|
||||||
Process p = Runtime.getRuntime().exec(String.format(command, documentConfig.getOpenOfficeHome()));
|
|
||||||
OpenOfficeConnection connection = new SocketOpenOfficeConnection();
|
|
||||||
connection.connect();
|
|
||||||
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
DefaultDocumentFormatRegistry formatRegistry = new DefaultDocumentFormatRegistry();
|
|
||||||
converter.convert(new ByteArrayInputStream(source), formatRegistry.getFormatByFileExtension(sourceExtension), bos, formatRegistry.getFormatByFileExtension(targetExtension));
|
|
||||||
connection.disconnect();
|
|
||||||
p.destroy();
|
|
||||||
log.info("openoffice convert {} to {} take time in millis:{}", sourceExtension, targetExtension, System.currentTimeMillis() - start);
|
|
||||||
return bos.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] fieldToWord(byte[] source, Map<String, Object> infoMap) {
|
|
||||||
return DocToPdfUtil.fieldToWord(source, infoMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] insertJpeg(byte[] source, String toFindText, byte[] imgSource, int width, int height) {
|
|
||||||
return DocToPdfUtil.insertJpeg(source, toFindText, imgSource, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] insertJpeg(byte[] source, String toFindText, List<byte[]> imgSource, int width, int height) {
|
|
||||||
return DocToPdfUtil.insertJpeg(source, toFindText, imgSource, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] wordToPdf(byte[] source, String sourceExtension, boolean clear) {
|
|
||||||
try {
|
|
||||||
if (clear) {
|
|
||||||
source = DocToPdfUtil.clearPlaceholder(source);
|
|
||||||
}
|
|
||||||
return convert(source, sourceExtension, "pdf");
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] convert(byte[] source, String sourceExtension, String targetExtension, String targetFormat) {
|
|
||||||
return convert(source, sourceExtension, targetExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] wordToImage(byte[] source, String sourceExtension, String targetExtension) {
|
|
||||||
try {
|
|
||||||
byte[] pdfBytes = wordToPdf(source, sourceExtension, true);
|
|
||||||
PDDocument document = PDDocument.load(new ByteArrayInputStream(pdfBytes));
|
|
||||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
|
||||||
BufferedImage bim = pdfRenderer.renderImageWithDPI(
|
|
||||||
0, 300, ImageType.RGB);
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
ImageIOUtil.writeImage(bim, targetExtension, bos, 300);
|
|
||||||
document.close();
|
|
||||||
return bos.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] docToDocx(byte[] source) {
|
|
||||||
return convert(source, "doc", "docx");
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] xlsToXlsx(byte[] source) {
|
|
||||||
return convert(source, "xls", "xlsx");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,493 +0,0 @@
|
|||||||
package com.optima.document.server.utils;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xianjun on 2016/6/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转型操作工具类
|
|
||||||
*/
|
|
||||||
public final class CastUtil {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为String 型 默认为空
|
|
||||||
*/
|
|
||||||
public static String castString(Object obj) {
|
|
||||||
return CastUtil.castString(obj, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为String 型(提供默认值)
|
|
||||||
*/
|
|
||||||
public static String castString(Object obj, String defaultValue) {
|
|
||||||
return obj != null ? String.valueOf(obj) : defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为double型 默认为0
|
|
||||||
*/
|
|
||||||
public static double castDouble(Object obj) {
|
|
||||||
return CastUtil.castDouble(obj, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为double型(提供默认值)
|
|
||||||
*/
|
|
||||||
public static double castDouble(Object obj, double defaultValue) {
|
|
||||||
double doubleValue = defaultValue;
|
|
||||||
if (obj != null) {
|
|
||||||
String strValue = castString(obj);
|
|
||||||
if (StringUtils.isNotEmpty(strValue)) {
|
|
||||||
try {
|
|
||||||
doubleValue = Double.parseDouble(strValue);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
doubleValue = defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return doubleValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为long型,默认值为0
|
|
||||||
*/
|
|
||||||
public static long castLong(Object obj) {
|
|
||||||
return CastUtil.castLong(obj, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转换为long型(提供默认值)
|
|
||||||
*/
|
|
||||||
public static long castLong(Object obj, long defaultValue) {
|
|
||||||
long longValue = defaultValue;
|
|
||||||
if (obj != null) {
|
|
||||||
String strValue = castString(obj);
|
|
||||||
if (!StringUtils.isEmpty(strValue)) {
|
|
||||||
try {
|
|
||||||
longValue = Long.parseLong(strValue);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
longValue = defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return longValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为int型 默认值为0
|
|
||||||
*/
|
|
||||||
public static int castInt(Object obj) {
|
|
||||||
return CastUtil.castInt(obj, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为int型(提供默认值)
|
|
||||||
*/
|
|
||||||
public static int castInt(Object obj, int defaultValue) {
|
|
||||||
int intValue = defaultValue;
|
|
||||||
if (obj != null) {
|
|
||||||
String strValue = castString(obj);
|
|
||||||
if (StringUtils.isNotEmpty(strValue)) {
|
|
||||||
try {
|
|
||||||
intValue = Integer.parseInt(strValue);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
intValue = defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return intValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为double型,默认值为false
|
|
||||||
*/
|
|
||||||
public static boolean castBoolean(Object obj) {
|
|
||||||
return CastUtil.castBoolean(obj, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转为double型,提供默认值
|
|
||||||
*/
|
|
||||||
public static boolean castBoolean(Object obj, boolean defaultValue) {
|
|
||||||
boolean booleanValue = defaultValue;
|
|
||||||
if (obj != null) {
|
|
||||||
booleanValue = Boolean.parseBoolean(castString(obj));
|
|
||||||
}
|
|
||||||
return booleanValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转时间戳为date类型
|
|
||||||
*
|
|
||||||
* @param time
|
|
||||||
* @param defaultValue
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static Date castDate(long time, Date defaultValue) {
|
|
||||||
Date dateValue = defaultValue;
|
|
||||||
if (time != 0) {
|
|
||||||
DateTime dateTime = new DateTime(time);
|
|
||||||
dateValue = dateTime.toDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dateValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Date castDateNo(long time) {
|
|
||||||
return castDate(time, new Date(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转时间戳为date类型
|
|
||||||
*/
|
|
||||||
public static Date castDate(long time) {
|
|
||||||
return castDate(time, new Date());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取开始时间
|
|
||||||
*
|
|
||||||
* @Title: getStartTime
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param date
|
|
||||||
* @param monthTime
|
|
||||||
* @param dateTime
|
|
||||||
* @param hour
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static Date getStartTime(Date date, int monthTime, int dateTime, int hour) {
|
|
||||||
Calendar calendar = Calendar.getInstance();
|
|
||||||
calendar.set(CastUtil.castInt(CastUtil.castStringByDate(date, "yyyy")), date.getMonth() + monthTime, date.getDate() + dateTime, 0 + hour, 0, 0);
|
|
||||||
return calendar.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取结束时间
|
|
||||||
*
|
|
||||||
* @Title: getEndTime
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param date
|
|
||||||
* @param monthTime
|
|
||||||
* @param dateTime
|
|
||||||
* @param hour
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static Date getEndTime(Date date, int monthTime, int dateTime, int hour) {
|
|
||||||
Calendar calendar = Calendar.getInstance();
|
|
||||||
calendar.set(CastUtil.castInt(CastUtil.castStringByDate(date, "yyyy")), date.getMonth() + monthTime, date.getDate() + dateTime, 23 + hour, 59, 59);
|
|
||||||
return calendar.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转日期格式为字符串
|
|
||||||
*/
|
|
||||||
public static String castStringDate(Date date, Date defaultValue) {
|
|
||||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
Date dateValue = defaultValue;
|
|
||||||
String dateString = "";
|
|
||||||
if (date != null) {
|
|
||||||
dateString = fmt.format(date);
|
|
||||||
} else {
|
|
||||||
dateString = fmt.format(dateValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dateString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转换日期格式为年-月-日
|
|
||||||
* @Title: castStringIntegerDate
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param date
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static String castStringIntegerDate(Date date) {
|
|
||||||
return castStringIntegerDate(date, new Date());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转换格式为年-月-日
|
|
||||||
* @Title: castStringIntegerDate
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param date
|
|
||||||
* @param defaultValue
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static String castStringIntegerDate(Date date, Date defaultValue) {
|
|
||||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
|
|
||||||
Date dateValue = defaultValue;
|
|
||||||
String dateString = "";
|
|
||||||
if (date != null) {
|
|
||||||
dateString = fmt.format(date);
|
|
||||||
} else {
|
|
||||||
dateString = fmt.format(dateValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dateString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据传入的格式,转换为不同的日期
|
|
||||||
*
|
|
||||||
* @Title: castStringByDate
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param date
|
|
||||||
* @param pattern
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static String castStringByDate(Date date, String pattern) {
|
|
||||||
SimpleDateFormat fmt = new SimpleDateFormat(pattern);
|
|
||||||
Date dateValue = new Date();
|
|
||||||
String dateString = "";
|
|
||||||
if (date != null) {
|
|
||||||
dateString = fmt.format(date);
|
|
||||||
} else {
|
|
||||||
dateString = fmt.format(dateValue);
|
|
||||||
}
|
|
||||||
return dateString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转日期格式为字符串
|
|
||||||
*/
|
|
||||||
public static String castStringDate(Date date) {
|
|
||||||
return castStringDate(date, new Date());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转 字符串为日期格式
|
|
||||||
*/
|
|
||||||
public static Date castDateByString(String defaultDate){
|
|
||||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
try {
|
|
||||||
Date date = fmt.parse(defaultDate);
|
|
||||||
return date;
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return new Date();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转BigDecimal为字符串
|
|
||||||
*/
|
|
||||||
public static String castStringByDecimal(BigDecimal value, String pattern) {
|
|
||||||
DecimalFormat fmt = new DecimalFormat(pattern);
|
|
||||||
try {
|
|
||||||
String tempValue = fmt.format(value.stripTrailingZeros());
|
|
||||||
return tempValue;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// TODO: handle exception
|
|
||||||
e.printStackTrace();
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转换字符串,判断是否非空
|
|
||||||
* @Title: castStringByString
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param defaultString
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static String castStringByString(String defaultString) {
|
|
||||||
String value = defaultString == null ? "" : defaultString;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 去除html标签
|
|
||||||
* @Title: delHTMLTag
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param htmlStr
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static String delHTMLTag(String htmlStr){
|
|
||||||
String regEx_script="<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
|
|
||||||
String regEx_style="<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
|
|
||||||
String regEx_html="<[^>]+>"; //定义HTML标签的正则表达式
|
|
||||||
|
|
||||||
Pattern p_script=Pattern.compile(regEx_script,Pattern.CASE_INSENSITIVE);
|
|
||||||
Matcher m_script=p_script.matcher(htmlStr);
|
|
||||||
htmlStr=m_script.replaceAll(""); //过滤script标签
|
|
||||||
|
|
||||||
Pattern p_style=Pattern.compile(regEx_style,Pattern.CASE_INSENSITIVE);
|
|
||||||
Matcher m_style=p_style.matcher(htmlStr);
|
|
||||||
htmlStr=m_style.replaceAll(""); //过滤style标签
|
|
||||||
|
|
||||||
Pattern p_html=Pattern.compile(regEx_html,Pattern.CASE_INSENSITIVE);
|
|
||||||
Matcher m_html=p_html.matcher(htmlStr);
|
|
||||||
htmlStr=m_html.replaceAll(""); //过滤html标签
|
|
||||||
|
|
||||||
return htmlStr.trim(); //返回文本字符串
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过身份证号码获取出生日期、性别、年龄
|
|
||||||
* @author xianjun
|
|
||||||
* @param certificateNo
|
|
||||||
* @return 返回的出生日期格式:1990-01-01 性别格式:F-女,M-男
|
|
||||||
*/
|
|
||||||
public static Map<String, String> getBirAgeSex(String certificateNo) {
|
|
||||||
String birthday = "";
|
|
||||||
String age = "";
|
|
||||||
String sexCode = "";
|
|
||||||
|
|
||||||
int year = Calendar.getInstance().get(Calendar.YEAR);
|
|
||||||
char[] number = certificateNo.toCharArray();
|
|
||||||
boolean flag = true;
|
|
||||||
if (number.length == 15) {
|
|
||||||
for (int x = 0; x < number.length; x++) {
|
|
||||||
if (!flag) return new HashMap<String, String>();
|
|
||||||
flag = Character.isDigit(number[x]);
|
|
||||||
}
|
|
||||||
} else if (number.length == 18) {
|
|
||||||
for (int x = 0; x < number.length - 1; x++) {
|
|
||||||
if (!flag) return new HashMap<String, String>();
|
|
||||||
flag = Character.isDigit(number[x]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flag && certificateNo.length() == 15) {
|
|
||||||
birthday = "19" + certificateNo.substring(6, 8) + "-"
|
|
||||||
+ certificateNo.substring(8, 10) + "-"
|
|
||||||
+ certificateNo.substring(10, 12);
|
|
||||||
sexCode = Integer.parseInt(certificateNo.substring(certificateNo.length() - 3, certificateNo.length())) % 2 == 0 ? "F" : "M";
|
|
||||||
age = (year - Integer.parseInt("19" + certificateNo.substring(6, 8))) + "";
|
|
||||||
} else if (flag && certificateNo.length() == 18) {
|
|
||||||
birthday = certificateNo.substring(6, 10) + "-"
|
|
||||||
+ certificateNo.substring(10, 12) + "-"
|
|
||||||
+ certificateNo.substring(12, 14);
|
|
||||||
sexCode = Integer.parseInt(certificateNo.substring(certificateNo.length() - 4, certificateNo.length() - 1)) % 2 == 0 ? "F" : "M";
|
|
||||||
age = (year - Integer.parseInt(certificateNo.substring(6, 10))) + "";
|
|
||||||
}
|
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
|
||||||
map.put("birthday", birthday);
|
|
||||||
map.put("age", age);
|
|
||||||
map.put("sexCode", sexCode);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description 将Date类型的时间转为long类型的时间戳
|
|
||||||
* @Author SuXingYong
|
|
||||||
* @Date 2020/1/10 10:40
|
|
||||||
* @Param [date]
|
|
||||||
* @Return long
|
|
||||||
**/
|
|
||||||
public static long castDateForLong(Date date){
|
|
||||||
long result = 0;
|
|
||||||
if (date != null){
|
|
||||||
result = date.getTime();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description 将 yyyy-MM-dd HH:mm:ss 类型的时间字符串转换为long类型的时间戳
|
|
||||||
* @Author SuXingYong
|
|
||||||
* @Date 2020/1/10 10:46
|
|
||||||
* @Param [dateStr]
|
|
||||||
* @Return long
|
|
||||||
**/
|
|
||||||
public static long castDateStrForLong(String dateStr){
|
|
||||||
long result = 0;
|
|
||||||
Date date = CastUtil.castDateByString(dateStr);
|
|
||||||
if (date != null){
|
|
||||||
result = date.getTime();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description 将java.sql.Timestamp转化为对应格式的String
|
|
||||||
* @Author SuXingYong
|
|
||||||
* @Date 2020/3/10 15:13
|
|
||||||
* @Param [time, strFormat]
|
|
||||||
* @Return java.lang.String
|
|
||||||
**/
|
|
||||||
public static String castTimestampForString(java.sql.Timestamp time, String strFormat) {
|
|
||||||
DateFormat df = new SimpleDateFormat(strFormat);
|
|
||||||
String str = df.format(time);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取某年某月的第一天
|
|
||||||
* @author xianjun
|
|
||||||
* @param year
|
|
||||||
* @param month
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getFirstDayByMonth(int year, int month) {
|
|
||||||
Calendar cal = Calendar.getInstance();
|
|
||||||
// 设置年份
|
|
||||||
cal.set(Calendar.YEAR,year);
|
|
||||||
// 设置月份
|
|
||||||
cal.set(Calendar.MONTH, month-1);
|
|
||||||
// 获取某月最小天数
|
|
||||||
int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
|
|
||||||
// 设置最小天数
|
|
||||||
cal.set(Calendar.DAY_OF_MONTH, firstDay);
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
// 格式化
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
String firstDayOfMonth = sdf.format(cal.getTime());
|
|
||||||
return firstDayOfMonth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取某年某月的最后一天
|
|
||||||
*
|
|
||||||
* @author xianjun
|
|
||||||
* @param year
|
|
||||||
* @param month
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getLastDayByMonth(int year, int month) {
|
|
||||||
Calendar cal = Calendar.getInstance();
|
|
||||||
// 设置年份
|
|
||||||
cal.set(Calendar.YEAR, year);
|
|
||||||
// 设置月份
|
|
||||||
cal.set(Calendar.MONTH, month-1);
|
|
||||||
// 获取某月最大天数
|
|
||||||
int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
|
|
||||||
// 设置日历中月份的最大天数
|
|
||||||
cal.set(Calendar.DAY_OF_MONTH, lastDay);
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 23);
|
|
||||||
// 格式化时间
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
String lastDayOfMonth = sdf.format(cal.getTime());
|
|
||||||
return lastDayOfMonth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,792 +0,0 @@
|
|||||||
package com.optima.document.server.utils;
|
|
||||||
|
|
||||||
import com.jacob.activeX.ActiveXComponent;
|
|
||||||
import com.jacob.com.ComThread;
|
|
||||||
import com.jacob.com.Dispatch;
|
|
||||||
import com.jacob.com.Variant;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xianjun
|
|
||||||
* @version 2017年4月20日 上午10:48:46 word转pdf工具类
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class DocToPdfUtil {
|
|
||||||
|
|
||||||
private static final int wdFormatPDF = 17; // pdf格式
|
|
||||||
private static final int xlTypePDF = 0;
|
|
||||||
private static final int ppSaveAsPDF = 32;
|
|
||||||
// 代表一个word 程序
|
|
||||||
private static ActiveXComponent MsWordApp = null;
|
|
||||||
// 代表进行处理的word 文档
|
|
||||||
private static Dispatch document = null;
|
|
||||||
// word文档
|
|
||||||
private Dispatch doc;
|
|
||||||
// word运行程序
|
|
||||||
private ActiveXComponent word;
|
|
||||||
// 所有word文档集合
|
|
||||||
private Dispatch documents;
|
|
||||||
// 选定的范围和插入点
|
|
||||||
private Dispatch selection;
|
|
||||||
|
|
||||||
private boolean saveOnExit = true;
|
|
||||||
|
|
||||||
public DocToPdfUtil() throws Exception {
|
|
||||||
ComThread.InitSTA();
|
|
||||||
if (word == null) {
|
|
||||||
word = new ActiveXComponent("Word.Application");
|
|
||||||
// 不可见打开word
|
|
||||||
word.setProperty("Visible", new Variant(false));
|
|
||||||
// 禁用宏
|
|
||||||
word.setProperty("AutomationSecurity", new Variant(3));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (documents == null)
|
|
||||||
documents = word.getProperty("Documents").toDispatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置退出时参数
|
|
||||||
*
|
|
||||||
* @Title: setSaveOnExit
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param saveOnExit true-退出时保存文件,false-退出时不保存文件
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public void setSaveOnExit(boolean saveOnExit) {
|
|
||||||
this.saveOnExit = saveOnExit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开一个已存在的文档
|
|
||||||
*
|
|
||||||
* @Title: openDocument
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param docPath
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public void openDocument(String docPath) {
|
|
||||||
closeDocument();
|
|
||||||
doc = Dispatch.call(documents, "Open", docPath).toDispatch();
|
|
||||||
selection = Dispatch.get(word, "Selection").toDispatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件保存或另存为路径
|
|
||||||
*
|
|
||||||
* @Title: save
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param savePath
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public void save(String savePath) {
|
|
||||||
Dispatch.call(Dispatch.call(word, "WordBasic").getDispatch(), "FileSaveAs", savePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭文档
|
|
||||||
* @Title: closeDocument
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param val 0不保存修改 -1 保存修改 -2 提示是否保存修改
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public void closeDocument(int val) {
|
|
||||||
Dispatch.call(doc, "Close", new Variant(val));
|
|
||||||
doc = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭当前word文档
|
|
||||||
*
|
|
||||||
* @Title: cloaseDocument
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public void cloaseDocument() {
|
|
||||||
if (doc != null) {
|
|
||||||
Dispatch.call(doc, "Save");
|
|
||||||
Dispatch.call(doc, "Close", new Variant(saveOnExit));
|
|
||||||
doc = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭全部应用
|
|
||||||
*
|
|
||||||
* @Title: close
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public void close() {
|
|
||||||
if (word != null) {
|
|
||||||
//Dispatch.call(word, "Quit");
|
|
||||||
word.invoke("Quit",0);
|
|
||||||
word = null;
|
|
||||||
}
|
|
||||||
selection = null;
|
|
||||||
documents = null;
|
|
||||||
ComThread.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* word转pdf
|
|
||||||
*
|
|
||||||
* @author xianjun
|
|
||||||
* @version 2017年4月20日 上午9:56:09
|
|
||||||
* @describe
|
|
||||||
* @param fromAddress
|
|
||||||
* 待转地址
|
|
||||||
* toAddress 新文件地址
|
|
||||||
*/
|
|
||||||
// public static String wordToPdf(String fromAddress) {
|
|
||||||
// //ActiveXComponent ax = null;
|
|
||||||
// String toAddress = splitSuffx(fromAddress);
|
|
||||||
// try {
|
|
||||||
// PoiWordUtil.wordToPdf(fromAddress,toAddress);
|
|
||||||
// return toAddress;
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /*try {
|
|
||||||
// long startTime = System.currentTimeMillis();
|
|
||||||
//
|
|
||||||
// *//**
|
|
||||||
// * 创建不同的控件调用不同的值 Word-Word.Application Excel-Excel.Application
|
|
||||||
// * Powerpoint-Powerpoint.Application Outlook-Outlook.Application
|
|
||||||
// *//*
|
|
||||||
// ax = new ActiveXComponent("Word.Application");
|
|
||||||
// *//**
|
|
||||||
// * 设置打开文件不可见
|
|
||||||
// *//*
|
|
||||||
// ax.setProperty("Visible", false);
|
|
||||||
// *//**
|
|
||||||
// * 获取word文档中所有内容
|
|
||||||
// *//*
|
|
||||||
// Dispatch docs = ax.getProperty("Documents").toDispatch();
|
|
||||||
// *//**
|
|
||||||
// * 打开word文档,并设置word为不可编辑和不需确认
|
|
||||||
// *//*
|
|
||||||
// Dispatch doc = Dispatch.call(docs, "Open", fromAddress, false, true).toDispatch();
|
|
||||||
// File tofile = new File(toAddress);
|
|
||||||
// if (tofile.exists()) {
|
|
||||||
// tofile.delete();
|
|
||||||
// }
|
|
||||||
// // word文件另存为pdf文件
|
|
||||||
// Dispatch.call(doc, "SaveAs", toAddress, wdFormatPDF);
|
|
||||||
// // 关闭word文档
|
|
||||||
// Dispatch.call(doc, "Close", false);
|
|
||||||
// long endTime = System.currentTimeMillis();
|
|
||||||
// System.out.println("转换完成,总共耗时" + (endTime - startTime));
|
|
||||||
// return toAddress;
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// System.out.println("=============Error:文档转换失败:" + e.getMessage());
|
|
||||||
// return null;
|
|
||||||
// } */
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static String wordToPdf(String fromAddress, String fileName) throws Exception{
|
|
||||||
// String fileRootPath = UploadFileUtils.getPath("write");
|
|
||||||
// String dateUrl = CastUtil.castStringByDate(new Date(), "yyyy-MM-dd");
|
|
||||||
// String htmlFileDirPath = File.separator + dateUrl;
|
|
||||||
// File htmlDirFile = new File(fileRootPath + htmlFileDirPath);
|
|
||||||
// if (!htmlDirFile.exists()) {
|
|
||||||
// htmlDirFile.mkdirs();
|
|
||||||
// }
|
|
||||||
// //html文件路径
|
|
||||||
// String pdfFilePath = htmlDirFile.getPath() + File.separator + fileName + "." + "pdf";
|
|
||||||
// long startTime = System.currentTimeMillis();
|
|
||||||
// File tofile = new File(pdfFilePath);
|
|
||||||
// if (tofile.exists()) {
|
|
||||||
// tofile.delete();
|
|
||||||
// }
|
|
||||||
// // word文件另存为pdf文件
|
|
||||||
// PoiWordUtil.wordToPdf(fromAddress,pdfFilePath);
|
|
||||||
// // 关闭word文档
|
|
||||||
// long endTime = System.currentTimeMillis();
|
|
||||||
// System.out.println("转换完成,总共耗时" + (endTime - startTime));
|
|
||||||
// return "/"+dateUrl + "/" + fileName + "." + "pdf";
|
|
||||||
// }
|
|
||||||
|
|
||||||
public static String excel2PDF(String fromAddress){
|
|
||||||
String toAddress = splitSuffx(fromAddress);
|
|
||||||
try{
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
ActiveXComponent app = new ActiveXComponent("Excel.Application");
|
|
||||||
app.setProperty("Visible", false);
|
|
||||||
Dispatch excels = app.getProperty("Workbooks").toDispatch();
|
|
||||||
Dispatch excel = Dispatch.call(excels,"Open",fromAddress,false,true).toDispatch();
|
|
||||||
File tofile = new File(toAddress);
|
|
||||||
if (tofile.exists()) {
|
|
||||||
tofile.delete();
|
|
||||||
}
|
|
||||||
Dispatch.call(excel,"ExportAsFixedFormat",xlTypePDF,toAddress);
|
|
||||||
Dispatch.call(excel, "Close",false);
|
|
||||||
long endTime = System.currentTimeMillis();
|
|
||||||
System.out.println("转换完成,总共耗时" + (endTime - startTime));
|
|
||||||
return toAddress;
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("=============Error:文档转换失败:" + e.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
public static String ppt2PDF(String fromAddress){
|
|
||||||
String toAddress = splitSuffx(fromAddress);
|
|
||||||
try{
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
ActiveXComponent app = new ActiveXComponent("PowerPoint.Application");
|
|
||||||
//app.setProperty("Visible", msofalse);
|
|
||||||
Dispatch ppts = app.getProperty("Presentations").toDispatch();
|
|
||||||
|
|
||||||
Dispatch ppt = Dispatch.call(ppts,
|
|
||||||
"Open",
|
|
||||||
fromAddress,
|
|
||||||
true,//ReadOnly
|
|
||||||
true,//Untitled指定文件是否有标题
|
|
||||||
false//WithWindow指定文件是否可见
|
|
||||||
).toDispatch();
|
|
||||||
|
|
||||||
Dispatch.call(ppt,
|
|
||||||
"SaveAs",
|
|
||||||
toAddress,
|
|
||||||
ppSaveAsPDF
|
|
||||||
);
|
|
||||||
|
|
||||||
Dispatch.call(ppt, "Close");
|
|
||||||
long endTime = System.currentTimeMillis();
|
|
||||||
System.out.println("转换完成,总共耗时" + (endTime - startTime));
|
|
||||||
return toAddress;
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("=============Error:文档转换失败:" + e.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 路径处理函数,提取路径后缀
|
|
||||||
*
|
|
||||||
* @author xianjun
|
|
||||||
* @version 2017年4月20日 上午10:54:49
|
|
||||||
* @describe
|
|
||||||
* @param fromAddress
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String splitSuffx(String fromAddress) {
|
|
||||||
String toAddress = fromAddress.substring(0, fromAddress.lastIndexOf(".") + 1);
|
|
||||||
toAddress = toAddress + "pdf";
|
|
||||||
return toAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从选定内容或插入点开始查找文本
|
|
||||||
*
|
|
||||||
* @param toFindText
|
|
||||||
* 要查找的文本
|
|
||||||
* @return boolean true-查找到并选中该文本,false-未查找到文本
|
|
||||||
*/
|
|
||||||
public static boolean find(ActiveXComponent ax,String toFindText) {
|
|
||||||
if (toFindText == null || toFindText.equals(""))
|
|
||||||
return false;
|
|
||||||
Dispatch selection = Dispatch.get(ax, "Selection").toDispatch(); // 输入内容需要的对象
|
|
||||||
// 从selection所在位置开始查询
|
|
||||||
Dispatch find1 = Dispatch.call(selection, "Find").toDispatch();
|
|
||||||
// 设置要查找的内容
|
|
||||||
Dispatch.put(find1, "Text", toFindText);
|
|
||||||
// 向前查找
|
|
||||||
Dispatch.put(find1, "Forward", "True");
|
|
||||||
// 设置格式
|
|
||||||
Dispatch.put(find1, "Format", "True");
|
|
||||||
// 大小写匹配
|
|
||||||
Dispatch.put(find1, "MatchCase", "True");
|
|
||||||
// 全字匹配
|
|
||||||
Dispatch.put(find1, "MatchWholeWord", "True");
|
|
||||||
// 查找并选中
|
|
||||||
return Dispatch.call(find1, "Execute").getBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 向文档中添加 一个图片,
|
|
||||||
public static void insertJpeg(ActiveXComponent ax,String toFindText,String jpegFilePath,int width,int height) {
|
|
||||||
Dispatch selection = Dispatch.get(ax, "Selection").toDispatch();
|
|
||||||
// Dispatch image = Dispatch.get(selection, "InLineShapes").toDispatch();
|
|
||||||
// Dispatch.call(image, "AddPicture", jpegFilePath);
|
|
||||||
|
|
||||||
|
|
||||||
if (find(ax,toFindText)) {
|
|
||||||
Dispatch picture = Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(), "AddPicture", jpegFilePath).toDispatch(); // 添加图片
|
|
||||||
Dispatch.call(picture, "Select"); // 选中图片
|
|
||||||
Dispatch.put(picture, "Width", new Variant(width)); // 图片的宽度
|
|
||||||
Dispatch.put(picture, "Height", new Variant(height)); // 图片的高度
|
|
||||||
Dispatch ShapeRange = Dispatch.call(picture, "ConvertToShape").toDispatch(); // 取得图片区域
|
|
||||||
Dispatch WrapFormat = Dispatch.get(ShapeRange, "WrapFormat").toDispatch(); // 取得图片的格式对象
|
|
||||||
Dispatch.put(WrapFormat, "Type", 7); // 设置环绕格式(0 - 7)下面是参数说明
|
|
||||||
|
|
||||||
// wdWrapInline 7 将形状嵌入到文字中。
|
|
||||||
// wdWrapNone 3 将形状放在文字前面。请参阅 wdWrapFront 。
|
|
||||||
// wdWrapSquare 0 使文字环绕形状。行在形状的另一侧延续。
|
|
||||||
// wdWrapThrough 2 使文字环绕形状。
|
|
||||||
// wdWrapTight 1 使文字紧密地环绕形状。
|
|
||||||
// wdWrapTopBottom 4 将文字放在形状的上方和下方。
|
|
||||||
// wdWrapBehind 5 将形状放在文字后面。
|
|
||||||
// wdWrapFront 6 将形状放在文字前面。
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 保存文档的更改
|
|
||||||
public static void save() {
|
|
||||||
Dispatch.call(document, "Save");
|
|
||||||
}
|
|
||||||
public static void closeDocument() {
|
|
||||||
// Close the document without saving changes
|
|
||||||
// 0 = wdDoNotSaveChanges
|
|
||||||
// -1 = wdSaveChanges
|
|
||||||
// -2 = wdPromptToSaveChanges
|
|
||||||
if(document != null) {
|
|
||||||
Dispatch.call(document, "Close", new Variant(false));
|
|
||||||
document = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void closeWord() {
|
|
||||||
Dispatch.call(MsWordApp, "Quit");
|
|
||||||
MsWordApp = null;
|
|
||||||
document = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void openAnExistsFileTest(String wordFilePath,String toFindText,String imagePath,int width,int height) {
|
|
||||||
ActiveXComponent ax = null;
|
|
||||||
ax = new ActiveXComponent("Word.Application");
|
|
||||||
ax.setProperty("Visible", new Variant(false));// 是否前台打开word 程序,或者后台运行
|
|
||||||
Dispatch documents = Dispatch.get(ax, "Documents").toDispatch();
|
|
||||||
documents = Dispatch.call(documents, "Open", wordFilePath,
|
|
||||||
new Variant(true)/* 是否进行转换ConfirmConversions */,
|
|
||||||
new Variant(false)/* 是否只读 */).toDispatch();
|
|
||||||
//Dispatch selection = Dispatch.get(MsWordApp, "Selection").toDispatch();
|
|
||||||
insertJpeg(ax,toFindText,imagePath,width,height); // 插入图片(注意刚打开的word,光标处于开头,故,图片在最前方插入)
|
|
||||||
// word文件另存为pdf文件
|
|
||||||
String toAddress = splitSuffx(wordFilePath);
|
|
||||||
Dispatch.call(documents, "Save");
|
|
||||||
//Dispatch.call(documents, "Quit");
|
|
||||||
Dispatch.call(documents, "SaveAs", toAddress, wdFormatPDF);
|
|
||||||
Dispatch.call(documents, "Close", new Variant(false));
|
|
||||||
//save();
|
|
||||||
//closeDocument();
|
|
||||||
//closeWord();
|
|
||||||
// 关闭word文档
|
|
||||||
//Dispatch.call(documents, "Close", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean findText(Dispatch selection, String toFindText,String matchWholeWord) {
|
|
||||||
return findText(selection, toFindText, matchWholeWord, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找文本
|
|
||||||
* @param selection
|
|
||||||
* @param toFindText
|
|
||||||
* @param matchWholeWord 匹配全词
|
|
||||||
* @param matchWildcards 使用通配符
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean findText(Dispatch selection, String toFindText,String matchWholeWord, boolean matchWildcards) {
|
|
||||||
if (toFindText == null || "".equals(toFindText))
|
|
||||||
return false;
|
|
||||||
// 从selection所在位置开始查询
|
|
||||||
Dispatch find1 = Dispatch.call(selection, "Find").toDispatch();
|
|
||||||
// 设置要查找的内容
|
|
||||||
Dispatch.put(find1, "Text", toFindText);
|
|
||||||
// 向前查找
|
|
||||||
Dispatch.put(find1, "Forward", "True");
|
|
||||||
// 通配符
|
|
||||||
Dispatch.put(find1, "MatchWildcards", matchWildcards);
|
|
||||||
// 设置格式
|
|
||||||
Dispatch.put(find1, "Format", "True");
|
|
||||||
// 大小写匹配
|
|
||||||
Dispatch.put(find1, "MatchCase", "False");
|
|
||||||
// 全字匹配
|
|
||||||
Dispatch.put(find1, "MatchWholeWord", matchWholeWord);
|
|
||||||
// 查找并选中
|
|
||||||
return Dispatch.call(find1, "Execute").getBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 插入图片
|
|
||||||
*
|
|
||||||
* @Title: insertJpeg
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param source
|
|
||||||
* @param toFindText
|
|
||||||
* @param imgSource
|
|
||||||
* @param width
|
|
||||||
* @param height
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static byte[] insertJpeg(byte[] source, String toFindText, byte[] imgSource, int width, int height) {
|
|
||||||
long t1 = System.currentTimeMillis();
|
|
||||||
DocToPdfUtil docToPdfUtil = null;
|
|
||||||
Path tempFilePath = null;
|
|
||||||
Path imgTempFilePath = null;
|
|
||||||
byte[] result = null;
|
|
||||||
try {
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
tempFilePath = Files.createTempFile(UUID.randomUUID().toString(), null);
|
|
||||||
Files.write(tempFilePath, source);
|
|
||||||
docToPdfUtil.openDocument(tempFilePath.toString());
|
|
||||||
if (docToPdfUtil.findText(docToPdfUtil.selection, toFindText,"True")) {
|
|
||||||
imgTempFilePath = Files.createTempFile(UUID.randomUUID().toString(), null);
|
|
||||||
Files.write(imgTempFilePath, imgSource);
|
|
||||||
Dispatch picture = Dispatch.call(Dispatch.get(docToPdfUtil.selection, "InLineShapes").toDispatch(), "AddPicture", imgTempFilePath.toString()).toDispatch(); // 添加图片
|
|
||||||
Dispatch.call(picture, "Select"); // 选中图片
|
|
||||||
if (width!=0) {
|
|
||||||
Dispatch.put(picture, "Width", new Variant(width)); // 图片的宽度
|
|
||||||
Dispatch.put(picture, "Height", new Variant(height)); // 图片的高度
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispatch ShapeRange = Dispatch.call(picture, "ConvertToShape").toDispatch(); // 取得图片区域
|
|
||||||
// Dispatch WrapFormat = Dispatch.get(ShapeRange, "WrapFormat").toDispatch(); // 取得图片的格式对象
|
|
||||||
// Dispatch.put(WrapFormat, "Type", 0); // 设置环绕格式(0 - 7)下面是参数说明
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if(docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
if (tempFilePath != null) {
|
|
||||||
try {
|
|
||||||
result = Files.readAllBytes(tempFilePath);
|
|
||||||
Files.delete(tempFilePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (imgTempFilePath != null) {
|
|
||||||
try {
|
|
||||||
Files.delete(imgTempFilePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("insert image=======consuming:{} milliseconds", System.currentTimeMillis() - t1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 插入图片
|
|
||||||
*
|
|
||||||
* @Title: insertJpeg
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param source
|
|
||||||
* @param toFindText
|
|
||||||
* @param imgSources
|
|
||||||
* @param width
|
|
||||||
* @param height
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static byte[] insertJpeg(byte[] source, String toFindText, List<byte[]> imgSources, int width, int height) {
|
|
||||||
DocToPdfUtil docToPdfUtil = null;
|
|
||||||
Path tempFilePath = null;
|
|
||||||
Path imgTempFilePath = null;
|
|
||||||
byte[] result = null;
|
|
||||||
try {
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
tempFilePath = Files.createTempFile(UUID.randomUUID().toString(), null);
|
|
||||||
Files.write(tempFilePath, source);
|
|
||||||
docToPdfUtil.openDocument(tempFilePath.toString());
|
|
||||||
String replaceText = "";
|
|
||||||
for (int i = 0; i < imgSources.size(); i++) {
|
|
||||||
replaceText += "${" + toFindText + "_" + i + "}";
|
|
||||||
}
|
|
||||||
String searchText = "${" + toFindText + "}";
|
|
||||||
boolean flag = docToPdfUtil.findText(docToPdfUtil.selection, searchText, "True");
|
|
||||||
if (flag) {
|
|
||||||
setKeyAndValue(docToPdfUtil, replaceText, searchText);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < imgSources.size(); i++) {
|
|
||||||
Dispatch.call(docToPdfUtil.selection,"HomeKey",new Variant(6));
|
|
||||||
if (docToPdfUtil.findText(docToPdfUtil.selection, "${" + toFindText + "_" + i + "}" ,"True")) {
|
|
||||||
imgTempFilePath = Files.createTempFile(UUID.randomUUID().toString(), null);
|
|
||||||
Files.write(imgTempFilePath, imgSources.get(i));
|
|
||||||
Dispatch picture = Dispatch.call(Dispatch.get(docToPdfUtil.selection, "InLineShapes").toDispatch(), "AddPicture", imgTempFilePath.toString()).toDispatch(); // 添加图片
|
|
||||||
Dispatch.call(picture, "Select"); // 选中图片
|
|
||||||
if (width != 0) {
|
|
||||||
Dispatch.put(picture, "Width", new Variant(width)); // 图片的宽度
|
|
||||||
Dispatch.put(picture, "Height", new Variant(height)); // 图片的高度
|
|
||||||
}
|
|
||||||
// Dispatch ShapeRange = Dispatch.call(picture, "ConvertToShape").toDispatch(); // 取得图片区域
|
|
||||||
// Dispatch WrapFormat = Dispatch.get(ShapeRange, "WrapFormat").toDispatch(); // 取得图片的格式对象
|
|
||||||
// Dispatch.put(WrapFormat, "Type", 0); // 设置环绕格式(0 - 7)下面是参数说明
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if(docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
if (tempFilePath != null) {
|
|
||||||
try {
|
|
||||||
result = Files.readAllBytes(tempFilePath);
|
|
||||||
Files.delete(tempFilePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (imgTempFilePath != null) {
|
|
||||||
try {
|
|
||||||
Files.delete(imgTempFilePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void insertJpeg(String wordFilePath, List<String> findTexts, List<String> imagePaths, List<Map<String, Object>> imageSelections) {
|
|
||||||
DocToPdfUtil docToPdfUtil = null;
|
|
||||||
try {
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
docToPdfUtil.openDocument(wordFilePath);
|
|
||||||
if (findTexts != null && findTexts.size() > 0) {
|
|
||||||
for (int i=0; i< findTexts.size(); i++) {
|
|
||||||
String toFindText = findTexts.get(i);
|
|
||||||
String imagePath = imagePaths.get(i);
|
|
||||||
Map<String, Object> imageSelection = imageSelections.get(i);
|
|
||||||
int height = CastUtil.castInt(imageSelection.get("Height"));
|
|
||||||
int width = CastUtil.castInt(imageSelection.get("Width"));
|
|
||||||
if (docToPdfUtil.findText(docToPdfUtil.selection, toFindText,"True")) {
|
|
||||||
Dispatch picture = Dispatch.call(Dispatch.get(docToPdfUtil.selection, "InLineShapes").toDispatch(), "AddPicture", imagePath).toDispatch(); // 添加图片
|
|
||||||
Dispatch.call(picture, "Select"); // 选中图片
|
|
||||||
if (width!=0) {
|
|
||||||
Dispatch.put(picture, "Width", new Variant(width)); // 图片的宽度
|
|
||||||
Dispatch.put(picture, "Height", new Variant(height)); // 图片的高度
|
|
||||||
}
|
|
||||||
|
|
||||||
Dispatch ShapeRange = Dispatch.call(picture, "ConvertToShape").toDispatch(); // 取得图片区域
|
|
||||||
Dispatch WrapFormat = Dispatch.get(ShapeRange, "WrapFormat").toDispatch(); // 取得图片的格式对象
|
|
||||||
Dispatch.put(WrapFormat, "Type", 0); // 设置环绕格式(0 - 7)下面是参数说明
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if(docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换字段
|
|
||||||
*
|
|
||||||
* @Title: wordFindReplace
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param wordpath
|
|
||||||
* @param oldtext
|
|
||||||
* @param newtext
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static String wordFindReplace(String wordpath,String oldtext,String newtext) {
|
|
||||||
DocToPdfUtil docToPdfUtil = null;
|
|
||||||
try {
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
docToPdfUtil.openDocument(wordpath);
|
|
||||||
boolean flag = docToPdfUtil.findText(docToPdfUtil.selection, oldtext,"True");
|
|
||||||
if (flag) {
|
|
||||||
Dispatch.put(docToPdfUtil.selection,"Text",newtext);
|
|
||||||
Dispatch.call(docToPdfUtil.selection, "MoveRight");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if(docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 向word填充属性字段
|
|
||||||
*
|
|
||||||
* @Title: fieldToWord
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param source 源
|
|
||||||
* @param infoMap 属性字段
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static byte[] fieldToWord(byte[] source, Map<String, Object> infoMap) {
|
|
||||||
long t1 = System.currentTimeMillis();
|
|
||||||
DocToPdfUtil docToPdfUtil = null;
|
|
||||||
Path tempFilePath = null;
|
|
||||||
byte[] result = null;
|
|
||||||
try {
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
tempFilePath = Files.createTempFile(UUID.randomUUID().toString(), null);
|
|
||||||
Files.write(tempFilePath, source);
|
|
||||||
docToPdfUtil.openDocument(tempFilePath.toString());
|
|
||||||
for (String key : infoMap.keySet()) {
|
|
||||||
String replaceText = "${" + key.trim() + "}";
|
|
||||||
boolean flag = docToPdfUtil.findText(docToPdfUtil.selection, replaceText,"True");
|
|
||||||
if (flag) {
|
|
||||||
String value = CastUtil.castString(infoMap.get(key));
|
|
||||||
setKeyAndValue(docToPdfUtil, value, replaceText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
if (tempFilePath != null) {
|
|
||||||
try {
|
|
||||||
result = Files.readAllBytes(tempFilePath);
|
|
||||||
Files.delete(tempFilePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("insert text=======consuming:{} milliseconds", System.currentTimeMillis() - t1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除占位符
|
|
||||||
* @param source
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static byte[] clearPlaceholder(byte[] source) {
|
|
||||||
long t1 = System.currentTimeMillis();
|
|
||||||
DocToPdfUtil docToPdfUtil = null;
|
|
||||||
Path tempFilePath = null;
|
|
||||||
byte[] result = null;
|
|
||||||
try {
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
tempFilePath = Files.createTempFile(UUID.randomUUID().toString(), null);
|
|
||||||
Files.write(tempFilePath, source);
|
|
||||||
docToPdfUtil.openDocument(tempFilePath.toString());
|
|
||||||
String replaceText = "$\\{*\\}";
|
|
||||||
boolean flag = docToPdfUtil.findText(docToPdfUtil.selection, replaceText, "True", true);
|
|
||||||
if (flag) {
|
|
||||||
setKeyAndValue(docToPdfUtil, "", replaceText, true);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
if (tempFilePath != null) {
|
|
||||||
try {
|
|
||||||
result = Files.readAllBytes(tempFilePath);
|
|
||||||
Files.delete(tempFilePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("clear placeholder=======consuming:{} milliseconds", System.currentTimeMillis() - t1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setKeyAndValue(DocToPdfUtil docToPdfUtil, String value, String replaceText) {
|
|
||||||
setKeyAndValue(docToPdfUtil, value, replaceText, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setKeyAndValue(DocToPdfUtil docToPdfUtil, String value,String replaceText, boolean matchWildcards) {
|
|
||||||
if (value == null) {
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
value = CastUtil.delHTMLTag(value);
|
|
||||||
if (value.indexOf("\n\n") != -1) {
|
|
||||||
value = value.replace("\n\n", CastUtil.castString((char) 11));
|
|
||||||
}
|
|
||||||
if (value.indexOf("\n") != -1) {
|
|
||||||
value = value.replace("\n", CastUtil.castString((char) 11));
|
|
||||||
}
|
|
||||||
|
|
||||||
Dispatch.put(docToPdfUtil.selection, "Text", value);
|
|
||||||
|
|
||||||
//Dispatch.call(docToPdfUtil.selection, "MoveStart");
|
|
||||||
Dispatch.call(docToPdfUtil.selection,"HomeKey",new Variant(6));
|
|
||||||
boolean flag = docToPdfUtil.findText(docToPdfUtil.selection, replaceText,"True", matchWildcards);
|
|
||||||
if (flag) {
|
|
||||||
setKeyAndValue(docToPdfUtil, value, replaceText, matchWildcards);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* word转pdf
|
|
||||||
* @Title: wordCnoverPdf
|
|
||||||
* @author: xianjun
|
|
||||||
* @Description: TODO
|
|
||||||
* @param fromAddress
|
|
||||||
* @return
|
|
||||||
* @throws
|
|
||||||
*/
|
|
||||||
public static String wordCnoverPdf(String fromAddress) {
|
|
||||||
String toAddress = splitSuffx(fromAddress);
|
|
||||||
DocToPdfUtil docToPdfUtil = null;
|
|
||||||
try {
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
docToPdfUtil = new DocToPdfUtil();
|
|
||||||
docToPdfUtil.openDocument(fromAddress);
|
|
||||||
File tofile = new File(toAddress);
|
|
||||||
if (tofile.exists()) {
|
|
||||||
tofile.delete();
|
|
||||||
}
|
|
||||||
// word文件另存为pdf文件
|
|
||||||
Dispatch.call(docToPdfUtil.doc, "SaveAs", toAddress, wdFormatPDF);
|
|
||||||
// 关闭word文档
|
|
||||||
long endTime = System.currentTimeMillis();
|
|
||||||
System.out.println("转换完成,总共耗时" + (endTime - startTime));
|
|
||||||
if(docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
return toAddress;
|
|
||||||
} catch (Exception e) {
|
|
||||||
if(docToPdfUtil != null) {
|
|
||||||
docToPdfUtil.cloaseDocument();
|
|
||||||
docToPdfUtil.close();
|
|
||||||
}
|
|
||||||
System.out.println("=============Error:文档转换失败:" + e.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,486 +0,0 @@
|
|||||||
package com.optima.document.server.utils;/**
|
|
||||||
* Created by xianjun on 2019/3/22.16:30
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.poi.hwpf.HWPFDocument;
|
|
||||||
import org.apache.poi.hwpf.model.PicturesTable;
|
|
||||||
import org.apache.poi.hwpf.usermodel.Bookmarks;
|
|
||||||
import org.apache.poi.hwpf.usermodel.Range;
|
|
||||||
import org.apache.poi.xwpf.usermodel.*;
|
|
||||||
import org.apache.xmlbeans.XmlToken;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
|
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
|
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure;
|
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文书替换工具类
|
|
||||||
* @author xianjun
|
|
||||||
* @version 2019/3/22 16:30
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class PoiWordUtil {
|
|
||||||
/**
|
|
||||||
* word为doc后缀
|
|
||||||
*/
|
|
||||||
private static final String DOC = "doc";
|
|
||||||
/**
|
|
||||||
* word为docx后缀
|
|
||||||
*/
|
|
||||||
private static final String DOCX = "docx";
|
|
||||||
/**
|
|
||||||
* 服务器为windows
|
|
||||||
*/
|
|
||||||
private static final String SYSTEM_TYPE_W = "Windows";
|
|
||||||
/**
|
|
||||||
* 服务器为Linux
|
|
||||||
*/
|
|
||||||
private static final String SYSTEM_TYPE_L = "Linux";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 错误消息
|
|
||||||
*/
|
|
||||||
private static String errorMsg = "";
|
|
||||||
/**
|
|
||||||
* 模板路径
|
|
||||||
*/
|
|
||||||
private static String templatePath = "";
|
|
||||||
/**
|
|
||||||
* 新文件的路径
|
|
||||||
*/
|
|
||||||
private static String newFilePath = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文书临时存放的目录
|
|
||||||
*/
|
|
||||||
private static String tempFilePath = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换模板方法
|
|
||||||
* @param path 文书路径
|
|
||||||
* @param tempPath 临时路径
|
|
||||||
* @param paramMap 替换参数
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
// public static Map<String,String> executeWord(String path, String tempPath, Map<String, Object> paramMap) throws Exception {
|
|
||||||
// //获取模板路径
|
|
||||||
// getTemplate(path);
|
|
||||||
// //获取新文件生成路径
|
|
||||||
// getFileStore(path);
|
|
||||||
// newFilePath = tempPath;
|
|
||||||
// //判断模板类型
|
|
||||||
// if(templatePath.endsWith(DOC)){
|
|
||||||
// //处理03版word
|
|
||||||
// //replaceWordDoc(paramMap);
|
|
||||||
// }else if(templatePath.endsWith(DOCX)){
|
|
||||||
// //处理07版word
|
|
||||||
// replaceWordDocx(paramMap);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //返回处理结果(新生成文件路径、错误信息)
|
|
||||||
// Map<String,String> map = new HashMap<String,String>();
|
|
||||||
// map.put("newFilePath", newFilePath);
|
|
||||||
// map.put("errorMsg", errorMsg);
|
|
||||||
// return map;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换模板文本内容(2007)
|
|
||||||
* @param paramMap 替换参数
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private static void replaceWordDocx(Map<String, Object> paramMap) throws Exception{
|
|
||||||
InputStream is = new FileInputStream(tempFilePath);
|
|
||||||
XWPFDocument doc = new XWPFDocument(is);
|
|
||||||
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
|
|
||||||
Iterator<XWPFTable> it = doc.getTablesIterator();
|
|
||||||
XWPFParagraph para;
|
|
||||||
XWPFTable patab;
|
|
||||||
//替换文本
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
para = iterator.next();
|
|
||||||
replaceInParaDocx(doc, para, paramMap);
|
|
||||||
}
|
|
||||||
while (it.hasNext()) {
|
|
||||||
patab = it.next();
|
|
||||||
List<XWPFTableRow> rows = patab.getRows();
|
|
||||||
for (int i = 0; i < rows.size(); i++) {
|
|
||||||
XWPFTableRow row = rows.get(i);//读取每一列数据
|
|
||||||
List<XWPFTableCell> cells = row.getTableCells();
|
|
||||||
for (int j = 0; j < cells.size(); j++) {
|
|
||||||
XWPFTableCell cell = cells.get(j);
|
|
||||||
//输出当前的单元格的数据
|
|
||||||
//System.out.print(cell.getText() + "\t");
|
|
||||||
List<XWPFParagraph> paragraphs = cell.getParagraphs();
|
|
||||||
for (XWPFParagraph xwpfParagraph : paragraphs) {
|
|
||||||
replaceInParaDocx(doc, xwpfParagraph, paramMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//写出文件
|
|
||||||
OutputStream out = new FileOutputStream(newFilePath);
|
|
||||||
doc.write(out);
|
|
||||||
//关闭输出流
|
|
||||||
close(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换方法(2007)
|
|
||||||
* @param para
|
|
||||||
* @param paramMap
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static void replaceInParaDocx(XWPFDocument doc, XWPFParagraph para, Map<String, Object> paramMap) throws Exception {
|
|
||||||
List<XWPFRun> runs;
|
|
||||||
Matcher matcher;
|
|
||||||
String imgPath = "";
|
|
||||||
int width = 100,height = 100;
|
|
||||||
String txt = para.getParagraphText();
|
|
||||||
if (matcher(txt.trim()).find()) {
|
|
||||||
runs = para.getRuns();
|
|
||||||
for (int i=0; i<runs.size(); i++) {
|
|
||||||
XWPFRun run = runs.get(i);
|
|
||||||
String runText = run.toString();
|
|
||||||
matcher = matcher(runText);
|
|
||||||
if (matcher.find()) {
|
|
||||||
Map<String,Object> infoMap = new HashMap<String,Object>();
|
|
||||||
if ((matcher = matcher(runText)).find()) {
|
|
||||||
System.err.println("查找替换标签:" + matcher.group());
|
|
||||||
String tx = matcher.group().substring(2,matcher.group().length()-1);
|
|
||||||
if (paramMap.get(tx) instanceof Map) {
|
|
||||||
infoMap = (Map<String,Object>)paramMap.get(tx);
|
|
||||||
if (runText.contains("_img") || runText.contains("_sign") || runText.contains("_map")) {
|
|
||||||
imgPath = CastUtil.castString(infoMap.get("Text"));
|
|
||||||
width = CastUtil.castInt(infoMap.get("Width"));
|
|
||||||
height = CastUtil.castInt(infoMap.get("Height"));
|
|
||||||
if (imgPath !=null && !"".equalsIgnoreCase(imgPath)) {
|
|
||||||
runText = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String tempText = CastUtil.castString(infoMap.get("Text"));
|
|
||||||
if (tempText != null && !"".equalsIgnoreCase(tempText)) {
|
|
||||||
runText = CastUtil.castString(infoMap.get("Text"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (runText.contains("_img") || runText.contains("_sign") || runText.contains("_map")) {
|
|
||||||
imgPath = CastUtil.castString(paramMap.get(tx));
|
|
||||||
if (imgPath !=null && !"".equalsIgnoreCase(imgPath)) {
|
|
||||||
runText = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String tempText = CastUtil.castString(paramMap.get(tx));
|
|
||||||
if (tempText != null && !"".equalsIgnoreCase(tempText)) {
|
|
||||||
runText = tempText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//直接调用XWPFRun的setText()方法设置文本时,在底层会重新创建一个XWPFRun,把文本附加在当前文本后面,
|
|
||||||
//所以我们不能直接设值,需要先删除当前run,然后再自己手动插入一个新的run。
|
|
||||||
para.removeRun(i);
|
|
||||||
XWPFRun newRun = para.insertNewRun(i);
|
|
||||||
newRun.setText(runText);
|
|
||||||
if(!infoMap.isEmpty()){
|
|
||||||
//设置字体样式
|
|
||||||
setFont(newRun, infoMap);
|
|
||||||
}
|
|
||||||
if(StringUtils.isNoneEmpty(imgPath)){
|
|
||||||
//获得当前CTInline
|
|
||||||
CTInline inline = newRun.getCTR().addNewDrawing().addNewInline();
|
|
||||||
doc.addPictureData(new FileInputStream(imgPath), 5);
|
|
||||||
insertPicture(doc, inline, width, height);
|
|
||||||
}
|
|
||||||
imgPath = "";
|
|
||||||
//infoMap.clear();
|
|
||||||
System.err.println("替换");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2007字体样式设置
|
|
||||||
* @param run
|
|
||||||
* @param param
|
|
||||||
*/
|
|
||||||
private static void setFont(XWPFRun run, Map<String,Object> param) {
|
|
||||||
CTRPr pRpr = null;
|
|
||||||
if (run.getCTR() != null) {
|
|
||||||
pRpr = run.getCTR().getRPr();
|
|
||||||
if (pRpr == null) {
|
|
||||||
pRpr = run.getCTR().addNewRPr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置字体
|
|
||||||
if(param.get("Name") != null){
|
|
||||||
CTFonts fonts = pRpr.isSetRFonts()?pRpr.getRFonts():pRpr.addNewRFonts();
|
|
||||||
fonts.setAscii(param.get("Name").toString());
|
|
||||||
fonts.setEastAsia(param.get("Name").toString());
|
|
||||||
fonts.setHAnsi(param.get("Name").toString());
|
|
||||||
}
|
|
||||||
//粗体
|
|
||||||
run.setBold(param.get("Bold")!=null?true:false);
|
|
||||||
//斜体
|
|
||||||
run.setItalic(param.get("Italic")!=null?true:false);
|
|
||||||
//下划线
|
|
||||||
if (param.get("Underline") != null) {
|
|
||||||
run.setUnderline(UnderlinePatterns.SINGLE);
|
|
||||||
}
|
|
||||||
//字体大小
|
|
||||||
if(param.get("Size") != null){
|
|
||||||
CTHpsMeasure sz = pRpr.isSetSz() ? pRpr.getSz() : pRpr.addNewSz();
|
|
||||||
sz.setVal(new BigInteger(param.get("Size").toString()));
|
|
||||||
CTHpsMeasure szCs = pRpr.isSetSzCs() ? pRpr.getSzCs() : pRpr.addNewSzCs();
|
|
||||||
szCs.setVal(new BigInteger(param.get("Size").toString()));
|
|
||||||
}
|
|
||||||
//字体颜色
|
|
||||||
if (param.get("Color") != null) {
|
|
||||||
run.setColor(param.get("Color").toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 插入图片
|
|
||||||
*
|
|
||||||
* @param document
|
|
||||||
* @param inline
|
|
||||||
* @param width
|
|
||||||
* @param height
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static void insertPicture(XWPFDocument document, CTInline inline, int width, int height) throws Exception {
|
|
||||||
int id = document.getAllPictures().size()-1;
|
|
||||||
final int EMU = 9525;
|
|
||||||
width *= EMU;
|
|
||||||
height *= EMU;
|
|
||||||
String blipId = document.getAllPictures().get(id).getPackageRelationship().getId();
|
|
||||||
|
|
||||||
String picXml = ""
|
|
||||||
+ "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
|
|
||||||
+ " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
|
|
||||||
+ " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
|
|
||||||
+ " <pic:nvPicPr>"
|
|
||||||
+ " <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>"
|
|
||||||
+ " <pic:cNvPicPr/>"
|
|
||||||
+ " </pic:nvPicPr>"
|
|
||||||
+ " <pic:blipFill>"
|
|
||||||
+ " <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
|
|
||||||
+ " <a:stretch>"
|
|
||||||
+ " <a:fillRect/>"
|
|
||||||
+ " </a:stretch>"
|
|
||||||
+ " </pic:blipFill>"
|
|
||||||
+ " <pic:spPr>"
|
|
||||||
+ " <a:xfrm>"
|
|
||||||
+ " <a:off x=\"0\" y=\"0\"/>"
|
|
||||||
+ " <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>"
|
|
||||||
+ " </a:xfrm>"
|
|
||||||
+ " <a:prstGeom prst=\"rect\">"
|
|
||||||
+ " <a:avLst/>"
|
|
||||||
+ " </a:prstGeom>"
|
|
||||||
+ " </pic:spPr>"
|
|
||||||
+ " </pic:pic>"
|
|
||||||
+ " </a:graphicData>"
|
|
||||||
+ "</a:graphic>";
|
|
||||||
|
|
||||||
inline.addNewGraphic().addNewGraphicData();
|
|
||||||
XmlToken xmlToken = null;
|
|
||||||
xmlToken = XmlToken.Factory.parse(picXml);
|
|
||||||
inline.set(xmlToken);
|
|
||||||
inline.setDistT(0);
|
|
||||||
inline.setDistB(0);
|
|
||||||
inline.setDistL(0);
|
|
||||||
inline.setDistR(0);
|
|
||||||
CTPositiveSize2D extent = inline.addNewExtent();
|
|
||||||
extent.setCx(width);
|
|
||||||
extent.setCy(height);
|
|
||||||
CTNonVisualDrawingProps docPr = inline.addNewDocPr();
|
|
||||||
docPr.setId(id);
|
|
||||||
docPr.setName("IMG_" + id);
|
|
||||||
docPr.setDescr("IMG_" + id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换模板文本内容(2003)
|
|
||||||
* @param paramMap 替换参数
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private static void replaceWordDoc(Map<String, Object> paramMap) throws Exception{
|
|
||||||
InputStream is = new FileInputStream(templatePath);
|
|
||||||
HWPFDocument doc = new HWPFDocument(is);
|
|
||||||
Range bodyRange = doc.getRange();
|
|
||||||
//替换文本
|
|
||||||
replaceInParaDoc(doc, bodyRange, paramMap);
|
|
||||||
//输出新文件
|
|
||||||
FileOutputStream out = new FileOutputStream(newFilePath);
|
|
||||||
doc.write(out);
|
|
||||||
out.flush();
|
|
||||||
//关闭输出流
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换方法(2003)
|
|
||||||
* @param range
|
|
||||||
* @param paramMap
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static void replaceInParaDoc(HWPFDocument doc, Range range, Map<String, Object> paramMap) {
|
|
||||||
Matcher matcher;
|
|
||||||
String imgPath = "";
|
|
||||||
int width = 0,height = 0;
|
|
||||||
while ((matcher = matcher(range.text())).find()) {
|
|
||||||
String key = matcher.group();
|
|
||||||
Map<String, Object> infoMap = (Map<String, Object>) paramMap.get(key);
|
|
||||||
if (infoMap.get("Type") !=null && "img".equalsIgnoreCase(CastUtil.castString(infoMap.get("Type")))) {
|
|
||||||
//处理图片
|
|
||||||
imgPath = infoMap.get("Path").toString();
|
|
||||||
width = Integer.parseInt(infoMap.get("Width").toString());
|
|
||||||
height = Integer.parseInt(infoMap.get("Height").toString());
|
|
||||||
} else {
|
|
||||||
range.replaceText(matcher.group(), String.valueOf(infoMap.get("Text")));
|
|
||||||
}
|
|
||||||
if(StringUtils.isNoneEmpty(imgPath)){
|
|
||||||
Bookmarks bookmarks = doc.getBookmarks();
|
|
||||||
PicturesTable picturesTable = doc.getPicturesTable();
|
|
||||||
}
|
|
||||||
imgPath = "";
|
|
||||||
/*int index = Integer.valueOf(matcher.group(1)) - 1;
|
|
||||||
if(index >= params.size()) break;
|
|
||||||
if(params.get(index) instanceof String){
|
|
||||||
range.replaceText(matcher.group(), String.valueOf(params.get(index)));
|
|
||||||
}else if(params.get(index) instanceof Map){
|
|
||||||
Map<String,Object> infoMap = (Map<String,Object>)params.get(index);
|
|
||||||
range.replaceText(matcher.group(), String.valueOf(infoMap.get("Text")));
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 正则匹配字符串
|
|
||||||
* @param str 带替换字符串
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static Matcher matcher(String str) {
|
|
||||||
String remax = "\\$.+?}";
|
|
||||||
//String remax = "\\$\\{(.+?)\\}"Pattern.CASE_INSENSITIVE;
|
|
||||||
Pattern pattern = Pattern.compile(remax);
|
|
||||||
Matcher matcher = pattern.matcher(str);
|
|
||||||
return matcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取文件模板路径
|
|
||||||
* @param path 模板文件路径
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private static void getTemplate(String path) throws Exception {
|
|
||||||
//String path = UploadFileUtils.getPath("write");
|
|
||||||
// String docPath = path + templateName + ".doc";
|
|
||||||
//String docxPath = path + templateName + ".docx";
|
|
||||||
templatePath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 获取文件存储路径
|
|
||||||
// * @param templatePath 模板文件名称
|
|
||||||
// * @return
|
|
||||||
// * @throws IOException
|
|
||||||
// */
|
|
||||||
// private static void getFileStore(String templatePath) throws IOException {
|
|
||||||
// //操作系统类型(Windows、Linux)
|
|
||||||
// String sysType = UploadFileUtils.getPath("fileserver.system.type");
|
|
||||||
// //文件存储跟目录
|
|
||||||
// String fileRoot = UploadFileUtils.getPath("fileserver.local.root");
|
|
||||||
// //文件生产目录
|
|
||||||
// String fileStore = UploadFileUtils.getPath("fileserver.store");
|
|
||||||
// //生成文件名称
|
|
||||||
// String name = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
|
|
||||||
//
|
|
||||||
// if(SYSTEM_TYPE_W.equals(sysType)){
|
|
||||||
// //Windows
|
|
||||||
// tempFilePath = fileRoot + fileStore + "/" ;
|
|
||||||
// }else if(SYSTEM_TYPE_L.equals(sysType)){
|
|
||||||
// //Linux
|
|
||||||
// tempFilePath = File.separator + "usr/fileserver/";
|
|
||||||
// }else{
|
|
||||||
// //其他服务器系统处理
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //生成目录不存在创建目录
|
|
||||||
// File file = new File(tempFilePath);
|
|
||||||
// if(!file.exists()){
|
|
||||||
// file.mkdirs();
|
|
||||||
// }
|
|
||||||
// tempFilePath = tempFilePath + name + ".docx";
|
|
||||||
// FileUtils.copyFile(templatePath, tempFilePath);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭输出流
|
|
||||||
* @param os
|
|
||||||
*/
|
|
||||||
public static void close(OutputStream os) {
|
|
||||||
if (os != null) {
|
|
||||||
try {
|
|
||||||
os.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭输入流
|
|
||||||
* @param in
|
|
||||||
*/
|
|
||||||
public static void close(InputStream in) {
|
|
||||||
if (in != null) {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* word转pdf
|
|
||||||
* @throws Exception
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
// public static byte[] wordToPdf(byte[] source) throws Exception{
|
|
||||||
// // 临时文件
|
|
||||||
// Path tempFilePath = Files.createTempFile(UUID.randomUUID().toString(), null);;
|
|
||||||
// Files.write(tempFilePath, source);
|
|
||||||
// String command = "D:/OpenOffice4/program/soffice.exe -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\"";
|
|
||||||
// Process p = Runtime.getRuntime().exec(command);
|
|
||||||
// OpenOfficeConnection connection = new SocketOpenOfficeConnection();
|
|
||||||
// connection.connect();
|
|
||||||
// // 转换
|
|
||||||
// DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
|
|
||||||
// converter.convert(new ByteArrayInputStream(source), tempFilePath.toString());
|
|
||||||
// // 关闭连接
|
|
||||||
// connection.disconnect();
|
|
||||||
// // 关闭进程
|
|
||||||
// p.destroy();
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
server:
|
|
||||||
port: 8090
|
|
||||||
document:
|
|
||||||
open-office-home: D:\\OpenOffice4\\program\\soffice.exe
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,96 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>2.0.3.RELEASE</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>com.optima</groupId>
|
|
||||||
<artifactId>document-tl-server</artifactId>
|
|
||||||
<version>2.0.0</version>
|
|
||||||
<name>document tl server</name>
|
|
||||||
<description>文档模版引擎服务</description>
|
|
||||||
<properties>
|
|
||||||
<java.version>1.8</java.version>
|
|
||||||
<tomcat.version>8.5.100</tomcat.version>
|
|
||||||
</properties>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.optima</groupId>
|
|
||||||
<artifactId>document-api</artifactId>
|
|
||||||
<version>2.0.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.16.20</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jodconverter</groupId>
|
|
||||||
<artifactId>jodconverter-core</artifactId>
|
|
||||||
<version>4.0.0-RELEASE</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>json</artifactId>
|
|
||||||
<groupId>org.json</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.pdfbox</groupId>
|
|
||||||
<artifactId>pdfbox-tools</artifactId>
|
|
||||||
<version>2.0.25</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.deepoove</groupId>
|
|
||||||
<artifactId>poi-tl</artifactId>
|
|
||||||
<version>1.12.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
|
||||||
<artifactId>log4j-to-slf4j</artifactId>
|
|
||||||
<version>2.17.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
|
||||||
<artifactId>log4j-api</artifactId>
|
|
||||||
<version>2.17.2</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<includeSystemScope>true</includeSystemScope>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
server:
|
|
||||||
port: 9004
|
|
||||||
document:
|
|
||||||
doc-to-program: C:\\DocumentServer\\docto.exe
|
|
||||||
Reference in New Issue
Block a user