之前写了一个版本的,不过代码繁琐而且不好用,效率有些问题。尤其pdf转图片速度太慢。下面是优化版本的代码。

spriing_boot 版本信息:2.0.1.RELEASE

优化版代码https://gitee.com/liran123/transfer_easy_fast

 

1、配置信息:

package com.yunfatong.conf;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.jodconverter.DocumentConverter;
import org.jodconverter.LocalConverter;
import org.jodconverter.office.LocalOfficeManager;
import org.jodconverter.office.OfficeManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.HashSet;
import java.util.Set; /**
* openoffice 配置
*
* @author liran
* @date 20190517
*/
@Configuration
@ConditionalOnClass({DocumentConverter.class})
@ConditionalOnProperty(prefix = "jodconverter", name = {"enabled"}, havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties({JodConverterProperties.class})
@Slf4j
public class JodConverterAutoConfiguration {
private final JodConverterProperties properties; public JodConverterAutoConfiguration(JodConverterProperties properties) {
this.properties = properties;
} private OfficeManager createOfficeManager() {
LocalOfficeManager.Builder builder = LocalOfficeManager.builder();
if (!StringUtils.isBlank(this.properties.getPortNumbers())) {
Set<Integer> iports = new HashSet<>();
String[] var3 = StringUtils.split(this.properties.getPortNumbers(), ", ");
int var4 = var3.length; for (int var5 = 0; var5 < var4; ++var5) {
String portNumber = var3[var5];
iports.add(NumberUtils.toInt(portNumber, 2002));
} builder.portNumbers(ArrayUtils.toPrimitive(iports.toArray(new Integer[iports.size()])));
}
builder.officeHome(this.properties.getOfficeHome());
builder.workingDir(this.properties.getWorkingDir());
builder.templateProfileDir(this.properties.getTemplateProfileDir());
builder.killExistingProcess(this.properties.isKillExistingProcess());
builder.processTimeout(this.properties.getProcessTimeout());
builder.processRetryInterval(this.properties.getProcessRetryInterval());
builder.taskExecutionTimeout(this.properties.getTaskExecutionTimeout());
builder.maxTasksPerProcess(this.properties.getMaxTasksPerProcess());
builder.taskQueueTimeout(this.properties.getTaskQueueTimeout());
return builder.build();
} @Bean(initMethod = "start", destroyMethod = "stop")
@ConditionalOnMissingBean
public OfficeManager officeManager() {
return this.createOfficeManager();
} @Bean
@ConditionalOnMissingBean
@ConditionalOnBean({OfficeManager.class})
public DocumentConverter jodConverter(OfficeManager officeManager) {
return LocalConverter.make(officeManager);
}
}
package com.yunfatong.conf;

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.regex.Pattern;

/**
* openoffice 配置
*
* @author liran
* @date 20190517
*/
@ConfigurationProperties("jodconverter")
public class JodConverterProperties {
private boolean enabled;
private String officeHome;
private String portNumbers = "2002";
private String workingDir;
private String templateProfileDir;
private boolean killExistingProcess = true;
private long processTimeout = 120000L;
private long processRetryInterval = 250L;
private long taskExecutionTimeout = 120000L;
private int maxTasksPerProcess = 200;
private long taskQueueTimeout = 30000L; public JodConverterProperties() {
} public boolean isEnabled() {
return this.enabled;
} public void setEnabled(boolean enabled) {
this.enabled = enabled;
} public String getOfficeHome() {
//根据不同系统分别设置
//office-home: C:\Program Files (x86)\OpenOffice 4 #windows下默认 不用修改
// #office-home: /opt/openoffice4 #linux 默认 不用修改
String osName = System.getProperty("os.name");
if (Pattern.matches("Linux.*", osName)) {
this.officeHome = "/opt/openoffice4";
} else if (Pattern.matches("Windows.*", osName)) {
this.officeHome = "C:\\Program Files (x86)\\OpenOffice 4";
} else {
this.officeHome = "/opt/openoffice4";
}
return this.officeHome;
} public void setOfficeHome(String officeHome) {
this.officeHome = officeHome;
} public String getPortNumbers() {
return this.portNumbers;
} public void setPortNumbers(String portNumbers) {
this.portNumbers = portNumbers;
} public String getWorkingDir() {
return this.workingDir;
} public void setWorkingDir(String workingDir) {
this.workingDir = workingDir;
} public String getTemplateProfileDir() {
return this.templateProfileDir;
} public void setTemplateProfileDir(String templateProfileDir) {
this.templateProfileDir = templateProfileDir;
} public boolean isKillExistingProcess() {
return this.killExistingProcess;
} public void setKillExistingProcess(boolean killExistingProcess) {
this.killExistingProcess = killExistingProcess;
} public long getProcessTimeout() {
return this.processTimeout;
} public void setProcessTimeout(long processTimeout) {
this.processTimeout = processTimeout;
} public long getProcessRetryInterval() {
return this.processRetryInterval;
} public void setProcessRetryInterval(long procesRetryInterval) {
this.processRetryInterval = procesRetryInterval;
} public long getTaskExecutionTimeout() {
return this.taskExecutionTimeout;
} public void setTaskExecutionTimeout(long taskExecutionTimeout) {
this.taskExecutionTimeout = taskExecutionTimeout;
} public int getMaxTasksPerProcess() {
return this.maxTasksPerProcess;
} public void setMaxTasksPerProcess(int maxTasksPerProcess) {
this.maxTasksPerProcess = maxTasksPerProcess;
} public long getTaskQueueTimeout() {
return this.taskQueueTimeout;
} public void setTaskQueueTimeout(long taskQueueTimeout) {
this.taskQueueTimeout = taskQueueTimeout;
}
}

application.yml

jodconverter:
enabled: true
office-home: linuxOrwindows
#/opt/openoffice4 #linux 默认 不用修改 C:\Program Files (x86)\OpenOffice 4 #windows下默认 不用修改
port-numbers: 2002
max-tasks-per-process: 10

2、转换入口

package com.yunfatong.ojd.util.pdf;

import cn.hutool.core.date.DatePattern;
import com.yunfatong.ojd.common.exception.CommonException;
import com.yunfatong.ojd.service.FileSystemStorageService;
import com.yunfatong.ojd.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jodconverter.DocumentConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List; /**
* word 转pdf
*
* @author lr
*/
@Component
@Slf4j
public class TransferUtil {
//这里没有@Autowired 主要是配置不启用的话 无法注入
private DocumentConverter documentConverter;
@Autowired
private FileSystemStorageService fileSystemStorageService;
/**
* fileSystemStorageService 就是拼接出本地路径的作用
* storage.winLocation=D:\\ojd\\upload\\images\\
* ##上传图片linux存储路径
* storage.linuxLocation=/home/ojd/upload/images/
*/ final static String WORD_SUFFIX_DOC = "doc";
final static String WORD_SUFFIX_DOCX = "docx"; /**
* word ->pdf
*
* @param webPath 浏览器可访问路径(数据库存的)如 /test/wd.word
* @return 相同文件夹下的转换后的pdf 路径 如/test/wd_20190517151515333.pdf
* @throws Exception
*/
public String transferWordToPdf(String webPath) throws Exception {
if(documentConverter==null){
documentConverter = SpringUtil.getBean(DocumentConverter.class);
}
//转换成本地实际磁盘路径
String originLocalFilePath = fileSystemStorageService.getLocation(webPath);
File inputFile = new File(originLocalFilePath);
if (!inputFile.exists() ||
        !inputFile.isFile() ||
         (!StringUtils.contains(inputFile.getName(), WORD_SUFFIX_DOC) &&
          !StringUtils.contains(inputFile.getName(), WORD_SUFFIX_DOCX))) {
throw new CommonException("word -> pdf转换错误 当前文件不是word或 文件不存在: " + webPath);
} DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_MS_PATTERN);
String timeNow = formatter.format(LocalDateTime.now());
String newPdfWebPath = StringUtils.substringBeforeLast(webPath, ".") + "_" + timeNow + ".pdf";
try {
File outputFile = new File(fileSystemStorageService.getLocation(newPdfWebPath));
documentConverter.convert(inputFile).to(outputFile).execute();
} catch (Exception e) {
log.error("word->pdf 转换错误------------> Exception:{}", e);
throw e;
}
return newPdfWebPath;
} public List<String> transferPdfToImage(String webPath) throws Exception {
String originLocalFilePath = fileSystemStorageService.getLocation(webPath);
File inputFile = new File(originLocalFilePath);
if (!inputFile.exists() ||
        !inputFile.isFile() ||
        webPath.lastIndexOf(".pdf") < 0) {
throw new CommonException("pdf-> img 源文件不是pdf文件 或者文件不存在!" + webPath);
}
String localPdfpath = fileSystemStorageService.getLocation(webPath);
String newImgWebPathPreSuffix = StringUtils.substringBeforeLast(webPath, ".");
String localImgPath = fileSystemStorageService.getLocation(newImgWebPathPreSuffix);
PdfTransferUtil pdfTranfer = new PdfTransferUtil();
List<byte[]> ins = pdfTranfer.pdf2Image(localPdfpath, "png", 1.5f);
List<String> webPaths = new ArrayList<>(ins.size());
for (int i = 0; i < ins.size(); i++) {
byte[] data = ins.get(i);
String pathReal = localImgPath + "_ojd_" + i + ".png";
FileUtils.writeByteArrayToFile(new File(pathReal), data);
webPaths.add(pathReal);
}
return webPaths;
} }

pdf 转图片参考 https://gitee.com/cycmy/pdftranfer.git

package com.yunfatong.ojd.util.pdf;

import lombok.extern.slf4j.Slf4j;
import org.icepdf.core.pobjects.Document;
import org.icepdf.core.pobjects.Page;
import org.icepdf.core.util.GraphicsRenderingHints; import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; /**
* @author lr
*
*/
@Slf4j
public class PdfTransferUtil { //*********************************pdf to image ********************************************************** /**
* 将指定pdf字节数组转换为指定格式图片二进制数组
*
* @param pdfBytes PDF字节数组
* @param imageType 转换图片格式 默认png
* @param zoom 缩略图显示倍数,1表示不缩放,0.3则缩小到30%
* @return List<byte [ ]>
* @throws Exception
*/
public List<byte[]> pdf2Image(byte[] pdfBytes, String imageType, float zoom) throws Exception {
Document document = new Document();
document.setByteArray(pdfBytes, 0, pdfBytes.length, null);
return pageExtraction(document, imageType, 0f, zoom);
} /**
* 将指定pdf输入流转换为指定格式图片二进制数组
*
* @param inputPDF PDF二进制流
* @param imageType 转换图片格式 默认png
* @param zoom 缩略图显示倍数,1表示不缩放,0.3则缩小到30%
* @return List<byte [ ]>
* @throws Exception
*/
public List<byte[]> pdf2Image(InputStream inputPDF, String imageType, float zoom) throws Exception { Document document = new Document();
document.setInputStream(inputPDF, null);
return pageExtraction(document, imageType, 0f, zoom);
} /**
* 将指定pdf文件转换为指定格式图片二进制数组
*
* @param pdfPath 原文件路径,例如d:/test.pdf
* @param imageType 转换图片格式 默认png
* @param zoom 缩略图显示倍数,1表示不缩放,0.3则缩小到30%
* @return List<byte [ ]>
* @throws Exception
*/
public List<byte[]> pdf2Image(String pdfPath, String imageType, float zoom) throws Exception {
Document document = new Document();
document.setFile(pdfPath);
return pageExtraction(document, imageType, 0f, zoom);
}
//*********************************pdf to image ********************************************************** private List<byte[]> pageExtraction(Document document, String imageType, float rotation, float zoom) {
// setup two threads to handle image extraction.
ExecutorService executorService = Executors.newFixedThreadPool(5);
try {
// create a list of callables.
int pages = document.getNumberOfPages();
List<byte[]> result = new ArrayList<byte[]>(pages);
List<Callable<byte[]>> callables = new ArrayList<Callable<byte[]>>(pages);
for (int i = 0; i < pages; i++) {
callables.add(new CapturePage(document, i, imageType, rotation, zoom));
}
List<Future<byte[]>> listFuture = executorService.invokeAll(callables);
executorService.submit(new DocumentCloser(document)).get();
for (Future<byte[]> future : listFuture) {
result.add(future.get());
}
return result;
} catch (Exception ex) {
log.error(" pdf 转换图片错误 Error handling PDF document " + ex);
} finally {
executorService.shutdown();
}
return null;
} public class CapturePage implements Callable<byte[]> {
private Document document;
private int pageNumber;
private String imageType;
private float rotation;
private float zoom; private CapturePage(Document document, int pageNumber, String imageType, float rotation, float zoom) {
this.document = document;
this.pageNumber = pageNumber;
this.imageType = imageType;
this.rotation = rotation;
this.zoom = zoom;
} @Override
public byte[] call() throws Exception {
BufferedImage image = (BufferedImage) document.getPageImage(pageNumber, GraphicsRenderingHints.SCREEN, Page.BOUNDARY_CROPBOX, rotation, zoom);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(image, imageType, imOut);
image.flush();
return bs.toByteArray();
}
} /**
* Disposes the document.
*/
public class DocumentCloser implements Callable<Void> {
private Document document; private DocumentCloser(Document document) {
this.document = document;
} @Override
public Void call() {
if (document != null) {
document.dispose();
log.info("Document disposed");
}
return null;
}
} }

springutils

package com.yunfatong.ojd.util;

/**
* @Auther liran
* @Date 2018/8/30 14:49
* @Description
*/
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; @Component
public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext="+SpringUtil.applicationContext+"========"); } //获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
} //通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
} //通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
} //通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
} }

pom.xml

  <!--word转换pdf begin-->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.2.2</version>
</dependency> <dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.2.2</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
<version>4.2.2</version>
</dependency>
<!--word转换pdf end--> <!--PDF转图片-->
<dependency>
<groupId>org.icepdf.os</groupId>
<artifactId>icepdf-core</artifactId>
<version>6.2.2</version>
<exclusions>
<exclusion>
<groupId>javax.media</groupId>
<artifactId>jai_core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.icepdf.os</groupId>
<artifactId>icepdf-viewer</artifactId>
<version>6.2.2</version>
</dependency>
<!--PDF转图片 end-->

3、调用测试:

import com.yunfatong.ojd.service.FileSystemStorageService;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class WordTransferPdfUtilTest {
@Autowired
TransferUtil wordTransferPdfUtil;
@Autowired
FileSystemStorageService fileSystemStorageService; @Test
public void transferLocalFile() {
   try {
/*******************word 转pdf******************/
long time = System.currentTimeMillis();
System.out.println("start :======" + time);
wordTransferPdfUtil.transferWordToPdf("courtChongqing/test_new/555.docx");
log.error(System.currentTimeMillis() + " time============================== :" + ((System.currentTimeMillis() - time) / 1000)); /*******************pdf转图片******************/
long time2 = System.currentTimeMillis();
List<String> pdfImages2 = wordTransferPdfUtil.transferPdfToImage("courtChongqing/test_new/333.pdf");
for (String pdfImage : pdfImages2) {
log.error(pdfImage);
}
log.error(" time===============================22222222 :" + ((System.currentTimeMillis() - time2) / 1000));
// System.out.println("pdf path =============" + path);
} catch (Exception e) {
e.printStackTrace();
}
 } }

openOffice word转pdf,pdf转图片优化版的更多相关文章

  1. word转PDF,PDF转Image,使用oppenOffice注意事项等

    最近在电子合同等项目中需要把word或者pdf转换成image,用到了openOffice把word转换pdf,以及把pdf转换成图片 感谢小伙伴张国清花费了三天时间来实现了此功能.下面我将把具体的步 ...

  2. C#将Word转换成PDF方法总结(基于Office和WPS两种方案)

    有时候,我们需要在线上预览word文档,当然我们可以用NPOI抽出Word中的文字和表格,然后显示到网页上面,但是这样会丢失掉Word中原有的格式和图片.一个比较好的办法就是将word转换成pdf,然 ...

  3. PHP pdf转化为图片(PNG)

    /** * 将pdf文件转化为多张png图片 * @param string $pdf pdf所在路径 (/www/pdf/abc.pdf pdf所在的绝对路径) * @param string $p ...

  4. pdf.js实现图片在线预览

    项目需求 前段时间项目中遇到了一个模块,是关于在线预览word文档(PDF文件)的,所以,找了很多插件,例如,pdf.js,pdfobject.js框架,但是pdfobject.js框架对于IE浏览器 ...

  5. C#——操作Word并导出PDF

    一.操作Word 首先引用这个DLL,Microsoft.Office.Interop.Word,官方提供的. 可以操作word文字,表格,图片等. 文字通过替换关键字的方式实现 document.P ...

  6. 一招教你如何用Word直接打开PDF进行编辑,无需下载转换软件

    我们都知道PDF是无法轻易修改的文档格式,市面上就出现了许多收费的如WPS等各种收费转换软件,免费的转换就只能转换几页,实属坑腰包,经过一番查找,终于发现Word可以直接打开PDF进行编辑,这一强大功 ...

  7. 微信小程序云开发-云存储-上传文件(word/excel/ppt/pdf)到云存储

    说明 word/excel/ppt/pdf是从客户端会话选择文件.使用chooseMessageFile中选择文件. 一.wxml文件 上传按钮,绑定chooseFile <!--上传文件(wo ...

  8. ITextSharp导出PDF表格和图片(C#)

    文章主要介绍使用ITextSharp导出PDF表格和图片的简单操作说明,以下为ITextSharp.dll下载链接 分享链接:http://pan.baidu.com/s/1nuc6glj 密码:3g ...

  9. Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结

    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结 1. office word  excel pdf 的web预览要求 ...

随机推荐

  1. BaseAdapter的优化

    传统的 package cct.commonadapter.bean; import android.content.Context; import android.view.LayoutInflat ...

  2. TCP/IP 协议、地址

    (一)TCP/IP 协议是端与端之间通信的基础,计算机网络,分组报文,协议是将信息正确传递的组成. 计算机网络: 由多个客户端,中间路由组成的网络体系,每个节点都一个ip进行唯一识别.路由是作为一个转 ...

  3. iOS Programming State Restoration 状态存储

    iOS Programming State Restoration 状态存储 If iOS ever needs more memory and your application is in the ...

  4. pjax

    下载地址: https://github.com/defunkt/jquery-pjax/find/master 使用方法: 0.先引入jquery和jquery.pjax.js 1.父页面定义区域d ...

  5. (转)Spring中的事务操作

    http://blog.csdn.net/yerenyuan_pku/article/details/70024364 事务的回顾 什么是事务 事务是逻辑上的一组操作,组成这组操作的各个逻辑单元,要么 ...

  6. 使用Latex插入数学公式(二)

    初级运算 关系运算符 希腊字母 集合运算符逻辑运算符 空格问题 矩阵格式 矩阵格式有三种: 无括号的矩阵 matrix 是 Latex 的矩阵命令,矩阵命令中每一行以 \\ 结束,矩阵的元素之间用 & ...

  7. rtim() 函数说明

    rtim() 函数 string rtrim ( string $str [, string $character_mask ] ) 该函数删除 str 末端的空白字符(或者其他字符)并返回. 不使用 ...

  8. python3中shuffle函数

    1. shuffle函数与其他函数不一样的地方 shuffle函数没有返回值!shuffle函数没有返回值!shuffle函数没有返回值!仅仅是实现了对list元素进行随机排序的一种功能 请看下面的坑 ...

  9. 第1节 MapReduce入门:11、mapreduce程序的入门

    1.1.理解MapReduce思想 MapReduce思想在生活中处处可见.或多或少都曾接触过这种思想.MapReduce的思想核心是“分而治之”,适用于大量复杂的任务处理场景(大规模数据处理场景). ...

  10. 树莓派 -- i2c学习 续(1) DeviceTree Overlay实例化rtc

    上文中讨论了通过sysfs来实例化i2c设备 (rtc ds3231) https://blog.csdn.net/feiwatson/article/details/81048616 本文继续看看如 ...