目的:将数据转换成word图片的方式展现给用户
工具:openoffice +java代码 +数据库,其中openoffice有windows版本的和Linux版本的。
其中openoffice的下载地址为:链接:https://pan.baidu.com/s/1Y5Ra3TfNCcvVX1bF-29hjw 密码:44ms
openoffice的安装及启动不在描述:网上自行百度。
下面主要是目的实现的步骤。
第一步:创建openoffice的连接池,使用linkedlist实现。简单的连接池,避免过多的消耗资源!
依赖的jar如下所以,部分jar无法下载,可以本地install 链接:https://pan.baidu.com/s/1wa65hYuxJ8wbIDETvuGDZQ 密码:pamx
<!--word转pdf以及pdf转图片使用的jar-->
<dependency>
<groupId>wisemax</groupId>
<artifactId>jodconverter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>ridl</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>com.artofsolving</groupId>
<artifactId>jodconverter</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>jurt</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>juh</artifactId>
<version>3.0.1</version>
</dependency>
<!--<dependency>-->
<!--<groupId>org.slf4j</groupId>-->
<!--<artifactId>slf4j-jdk14</artifactId>-->
<!--<version>1.5.6</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.icepdf</groupId>
<artifactId>icepdf-core</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>unoil</artifactId>
<version>3.2.1</version>
</dependency>
创建连接openoffice的类,模仿连接池的效果。
public class OpenSource {
private String url = "127.0.0.1";
private int port = 8100;
private static int initCount = 10;//初始化连接数
private static int maxCount = 15;//最大连接数
private static int currentCount = 10;//当前连接数
private static LinkedList<OpenOfficeConnection> connectionsPoll = new LinkedList<OpenOfficeConnection>();
public OpenSource() {
try {
for (int i = 0; i <= initCount; i++) {//初始化生成10个数据库连接
connectionsPoll.addLast(this.createConnection());
}
} catch (Exception e) {
e.printStackTrace();
}
}
private OpenOfficeConnection createConnection() throws Exception {
return new SocketOpenOfficeConnection(url, port);
}
public void free(OpenOfficeConnection conn) {
connectionsPoll.addLast(conn);//将连接放回连接池
System.out.println("连接池的大小为"+connectionsPoll.size());
}
public OpenOfficeConnection getConnection() throws Exception {
synchronized (connectionsPoll) {//多线程并发处理
if (connectionsPoll.size() > 0) {
return connectionsPoll.removeFirst();
} else if (currentCount < maxCount) {
//未超过最大连接数,则新建连接
OpenOfficeConnection conn = createConnection();
connectionsPoll.add(conn);
currentCount++;
return conn;
} else {
throw new RuntimeException("连接已经用完");
}
}
}
}
再创建一个工具类
public class OpenOfficeUtil {
private static OpenSource openOfficeSource = null;
public OpenOfficeUtil() {
}
static {
try {
openOfficeSource = new OpenSource();
} catch (Exception e) {
e.printStackTrace();
}
}
public static OpenOfficeConnection getConnection() throws Exception {
return openOfficeSource.getConnection();
}
public static void free(OpenOfficeConnection conn) {
openOfficeSource.free(conn);
}
private static int office2PDF(String sourceFile, String destFile, OpenOfficeConnection connection) {
try {
File inputFile = new File(sourceFile);
if (!inputFile.exists()) {
return -1;// 找不到源文件, 则返回-1
}
// 如果目标路径不存在, 则新建该路径
File outputFile = new File(destFile);
if (!outputFile.getParentFile().exists()) {
outputFile.getParentFile().mkdirs();
}
connection.connect();
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(inputFile, outputFile);
return 0;
} catch (Exception e) {
e.printStackTrace();
} finally {
free(connection);
}
return 1;
}
}
第二步:将数据转换成对应的模板信息。我利用的是github上的开源项目Word模板引擎 https://github.com/Sayi/poi-tl
具体的步骤和生成文档的方法,里面有很详细的介绍。
下面是我的模板样式:
其中带有{{xx}}为动态生成的数据。后台提供数据即可将数据写入到对应的变量中去。
第三步:生成数据到word文档
①:准备一个如上图所示的模板或者自己定义一个模板,将需要动态生成的数据用{{xx}}进行占位。
//根据word模板和相关数据生成word文档
private static String dataToWord(String templatePath) throws Exception {
//String templatePath = "D:\\worddata\\picc.docx";
XWPFTemplate template = XWPFTemplate.compile(templatePath).render(new HashMap<String, Object>() {{
put("caseNo", "订单信息");
put("info", "案件信息");
put("baoxian", "☑ 能繁母猪 □ 育肥猪");
put("baoxian", "今天");
}});
String filePath = "";
FileOutputStream out = new FileOutputStream("D:\\worddata\\out_template11.docx");
template.write(out);
out.flush();
out.close();
template.close();//多线程下是否需要close掉
return filePath;
}
如上代码便是将数据生成word的方法。输出路径为D:\\worddata\\out_template11.docx
其中map中put的key 是模板中的占位符变量。value是对应的值。
第四步:将word转换成pdf,此时要用到了openoffice工具。检查工具是否开启。
private static String officeToPdf(String sourceFile, String outPdfPath, String caseNo) throws Exception {
log.info("生成的PDF的路径为:{}", outPdfPath);
OpenOfficeConnection connection;
File inputFile = new File(sourceFile + File.separator + caseNo + ".docx");
if (!inputFile.exists()) {
return null;// 找不到源文件, 则返回-1
}
// 如果目标路径不存在, 则新建该路径
File outputFile = new File(outPdfPath + File.separator + caseNo + ".pdf");
if (!outputFile.getParentFile().exists()) {
outputFile.getParentFile().mkdirs();
}
//连接虚拟机上的openOffice
connection = OpenOfficeUtil.getConnection();
connection.connect();
// convert
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(inputFile, outputFile);
connection.disconnect();
//释放连接
OpenOfficeUtil.free(connection);
return outPdfPath + caseNo + ".pdf";
}
第五步:将pdf转成图片,图片的格式可以是png 或者jpg,图片的名字自定义。并且将下载的url返回
private String pdfToPicture(String pdfPath, String outPath, String caseNo) throws Exception {
String outImagePath = "";
Document document = new Document();
document.setFile(pdfPath);
//缩放比例
float scale = 2f;
//旋转角度
float rotation = 0f;
synchronized (this) {
for (int i = 0; i < document.getNumberOfPages(); i++) {
BufferedImage image = (BufferedImage)
document.getPageImage(i, GraphicsRenderingHints.SCREEN, org.icepdf.core.pobjects.Page.BOUNDARY_CROPBOX, rotation, scale);
RenderedImage rendImage = image;
try {
String imgName = i + ".png";
System.out.println(imgName);
File file = new File(outPath + caseNo + imgName);
if (1 == i) {
outImagePath = outPath + imgName;
}
ImageIO.write(rendImage, "png", file);
} catch (IOException e) {
log.error("PDF转成图片错误信息为:{}", e.getMessage());
}
image.flush();
}
}
document.dispose();
return outImagePath;
}
生成的图片部分
具体的位置可以进行调整。生成的文字样式可以根据github上的word模板引擎进行修改。里面有很详细的介绍。
提醒建议:
一:openoffice的安装,网上百度都有,很简单的,仔细阅读github上的开源项目。
二:生成word的模板是自己定义的,文字的位置加粗斜体下划线等由POI-tl提供,类似于freemaker。但是我觉得比freemaker好用些。
三:生成的word是一页,但是pdf可能是两页,最后转换图片是根据pdf的页数进行转换的,反正最后都是会转换的。
四:最后生成的图片url可以根据自身的需求进行修改。
五:jar包可能缺乏,博主的jar是刚好的,如果有冲突或者缺少,大家可以搜一下资料进行修改。
欢迎大家提出问题。