之前写了一个版本的,不过代码繁琐而且不好用,效率有些问题。尤其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. php之依赖注入和控制反转

      DI——Dependency Injection   依赖注入  IoC——Inversion of Control  控制反转  要想理解上面两个概念,就必须搞清楚如下的问题: 1.参与者都有谁 ...

  2. 一种结合hudson的算法自动化测试构想

    作者:朱金灿 来源:http://blog.csdn.net/clever101 有时我在思考:未来软件测试的趋势是什么?其实答案和其它行业一样简单:低技术含量的测试工作都将由机器承担,人只能干机器干 ...

  3. [转]JavaScript线程运行机制

    从开始接触js时,我们便知道js是单线程的.单线程,异步,同步,互调,阻塞等.在实际写js的时候,我们都会用到ajax,不管是原生的实现,还是借助jQuery等工具库实现,我们都知道,ajax可以实现 ...

  4. Maven之——使用本地jar包并打包进war包里面的方法

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/52594602 很显然,这种方法是很不可取的,因为Maven是用来团队合作,以及发布 ...

  5. OpenFlow_tutorial_2_Install_Required_Software

    一.Required Software 我操作系统用的 ubuntu 18.04.vm image的OS是ubuntu14.04,这两个系统的GUI应该已经不兼容了,如果使用ubuntu18.04的主 ...

  6. python学习(day2)

    1.常用数据类型及内置方法 1.列表(list) 定义:在中括号[]内存放任意多个值,用逗号隔开. 具体函数和内置方法如下: #定义学生列表,可存放多个学生 students=['a','b','c' ...

  7. MySQL for Mac 终端操作说明

    mysql for mac 终端操作说明MySQL服务开启Mac版mysql可以从设置里启动服务: 如果想要在终端(Terminal)中操作mysql,需要先添加mysql路径,在此以zsh为例: # ...

  8. VS2008 ActiveX(ocx控件)的调试工具ActiveX Control Test Container安装说明

    vs2008中的TSTCON( ActiveX Control Test Container )工具非自动安装,而是作为一个例程提供.所以应找到该例程,并编译: 如vs2008安装在默认路径则 1, ...

  9. vue之loader处理静态资源

    webpack 是利用loader 来处理各种资源的,wepback的配置基本上就是为各种资源文件,指定不同类型的loader. 1,处理css 最基本的css 处理loader 是css-loade ...

  10. java_线程的同步机制

    1.同步代码块: 使用synchronized包住可能会出现安全问题的代码 import static java.lang.Thread.sleep; class Test01{ public sta ...