1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > word文档转pdf 支持.doc和.docx

word文档转pdf 支持.doc和.docx

时间:2020-03-07 05:55:46

相关推荐

word文档转pdf 支持.doc和.docx

word文档有需要兼容.doc和.docx两种文档格式。其中.docx通过poi直接就可以将word转成pdf,.doc则无法这样实现,上网查询很多资料,大概思路是正确的,既将.doc文档转成html,再将html转成pdf,具体实现的时候,却发现很多方法都不完善,要么转换的html标签不闭合,无法转pdf,要么是转pdf时中文不显示,在下将方法汇总之后,整理出一套亲测可用的代码,现附上,如下:

maven依赖:

<!-- word转html -->

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi</artifactId>

<version>3.14</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi-scratchpad</artifactId>

<version>3.14</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi-ooxml</artifactId>

<version>3.14</version>

</dependency>

<dependency>

<groupId>fr.opensagres.xdocreport</groupId>

<artifactId>xdocreport</artifactId>

<version>1.0.6</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi-ooxml-schemas</artifactId>

<version>3.14</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>ooxml-schemas</artifactId>

<version>1.3</version>

</dependency>

<!-- /artifact/com.lowagie/itext -->

<!-- <dependency>

<groupId>com.lowagie</groupId>

<artifactId>itext</artifactId>

<version>2.0.8</version>

</dependency> -->

<!-- /artifact/org.xhtmlrenderer/core-renderer -->

<!-- html转pdf -->

<dependency>

<groupId>org.xhtmlrenderer</groupId>

<artifactId>core-renderer</artifactId>

<version>R8</version>

</dependency>

<!-- /artifact/org.jsoup/jsoup -->

<!-- html转xhtml -->

<dependency>

<groupId>org.jsoup</groupId>

<artifactId>jsoup</artifactId>

<version>1.11.3</version>

</dependency>

代码:

/**

*

*/

package cn.test.util.utils;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.transform.OutputKeys;

import javax.xml.transform.Transformer;

import javax.xml.transform.TransformerConfigurationException;

import javax.xml.transform.TransformerException;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import mons.collections.MapUtils;

import mons.lang.StringUtils;

import org.apache.poi.hwpf.HWPFDocument;

import org.apache.poi.hwpf.converter.PicturesManager;

import org.apache.poi.hwpf.converter.WordToHtmlConverter;

import org.apache.poi.hwpf.usermodel.Picture;

import org.apache.poi.hwpf.usermodel.PictureType;

import org.apache.poi.xwpf.converter.pdf.PdfConverter;

import org.apache.poi.xwpf.converter.pdf.PdfOptions;

import org.apache.poi.xwpf.usermodel.XWPFDocument;

import org.apache.poi.xwpf.usermodel.XWPFParagraph;

import org.apache.poi.xwpf.usermodel.XWPFRun;

import org.apache.poi.xwpf.usermodel.XWPFTable;

import org.apache.poi.xwpf.usermodel.XWPFTableCell;

import org.apache.poi.xwpf.usermodel.XWPFTableRow;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Entities;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.w3c.dom.Document;

import org.xhtmlrenderer.pdf.ITextFontResolver;

import org.xhtmlrenderer.pdf.ITextRenderer;

import com.itextpdf.text.DocumentException;

import com.itextpdf.text.pdf.PdfCopy;

import com.itextpdf.text.pdf.PdfImportedPage;

import com.itextpdf.text.pdf.PdfReader;

import com.lowagie.text.pdf.BaseFont;

/**

* @author gsxs

* <li>word转pdf工具类<li>

* @since 2月26日15:52:21

*/

public class Word2PDFUtils {

private static final Logger logger = LoggerFactory

.getLogger(Word2PDFUtils.class);

public static void main(String[] args) {

try {

word2PDF("D://Test/test.doc",

"D:/Test/test.pdf");

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

/**

* word文档转pdf,自动匹配.doc和.docx格式

*

* @param wordFilePath

* word文档路径

* @param pdfFilePath

* 欲输出pdf文档路径

* @throws Exception

*/

public static File word2PDF(String wordFilePath, String pdfFilePath)

throws Exception {

if (StringUtils.isBlank(pdfFilePath)

|| StringUtils.isBlank(wordFilePath)) {

logger.info("word2PDF 文件路径为空,wordFilePath={},pdfFilePath={}",

wordFilePath, pdfFilePath);

return null;

}

File wordFile = new File(wordFilePath);

File pdfFile = new File(pdfFilePath);

return word2PDF(wordFile, pdfFile);

}

/**

* word文档转pdf,自动匹配.doc和.docx格式

*

* @param wordFile

* word文档File对象

* @param pdfFile

* pdfFile对象

* @throws Exception

* @throws FileNotFoundException

*/

public static File word2PDF(File wordFile, File pdfFile) throws Exception {

if (null == wordFile || null == pdfFile) {

logger.info("word2PDF 文件对象为空,wordFile={},pdfFile={}", wordFile,

pdfFile);

return null;

}

String wordName = wordFile.getName();

if (!wordName.endsWith(".doc") && !wordName.endsWith(".docx")) {

// 格式不对

logger.info("不是word文档格式,文件路径={}", wordFile.getAbsolutePath());

return null;

}

File pdfParentFile = pdfFile.getParentFile();

if (!pdfParentFile.exists()) {

pdfParentFile.mkdirs();

}

String absolutePath = pdfParentFile.getAbsolutePath();

wordName = wordName.substring(0, wordName.indexOf("."));

String pdfPath = absolutePath + "/pdf/" + wordName + ".pdf";

File tempPdfFile = new File(pdfPath);

if (wordFile.getName().endsWith("doc")) {

String htmlPath = absolutePath + "/html/" + wordName + ".html";

File htmlFile = new File(htmlPath);

// doc格式word文档,先转成html,再格式化标签成xhtml,最后转成pdf

wordDocToHtml(wordFile, htmlFile);

convertHtmlToPdf(htmlFile, tempPdfFile);

// 删除html文件

boolean delete = htmlFile.delete();

logger.info("删除htmlFile路径path={},结果={}",

htmlFile.getAbsolutePath(), delete);

} else if (wordFile.getName().endsWith("docx")) {

// docx格式转pdf

wordConverterToPdf(new FileInputStream(wordFile),

new FileOutputStream(tempPdfFile), null);

}

// 抽取第一页

splitPDFFile(tempPdfFile.getAbsolutePath(), pdfFile.getAbsolutePath(),

1, 2);

// 删除临时的pdf文件

boolean delete = tempPdfFile.delete();

logger.info("删除tempPdfFile路径path={},结果={}",

tempPdfFile.getAbsolutePath(), delete);

return pdfFile;

}

/**

* 将word文档, 转换成pdf, 中间替换掉变量

*

* @param source

* 源为word文档, 必须为docx文档

* @param target

* 目标输出

* @param params

* 需要替换的变量

* @throws Exception

*/

private static void wordConverterToPdf(InputStream source,

OutputStream target, Map<String, String> params) throws Exception {

wordConverterToPdf(source, target, null, params);

}

/**

* 将word文档, 转换成pdf, 中间替换掉变量

*

* @param source

* 源为word文档, 必须为docx文档

* @param target

* 目标输出

* @param params

* 需要替换的变量

* @param options

* PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他

* @throws Exception

*/

private static void wordConverterToPdf(InputStream source,

OutputStream target, PdfOptions options, Map<String, String> params)

throws Exception {

XWPFDocument doc = new XWPFDocument(source);

paragraphReplace(doc.getParagraphs(), params);

// 存在需要替换的再循环

if (MapUtils.isNotEmpty(params)) {

for (XWPFTable table : doc.getTables()) {

for (XWPFTableRow row : table.getRows()) {

for (XWPFTableCell cell : row.getTableCells()) {

paragraphReplace(cell.getParagraphs(), params);

}

}

}

}

PdfConverter.getInstance().convert(doc, target, options);

}

/**

* 替换数据

*

* @param paragraphs

* @param params

*/

private static void paragraphReplace(List<XWPFParagraph> paragraphs,

Map<String, String> params) {

if (MapUtils.isNotEmpty(params)) {

for (XWPFParagraph p : paragraphs) {

for (XWPFRun r : p.getRuns()) {

String content = r.getText(r.getTextPosition());

if (StringUtils.isNotEmpty(content)

&& params.containsKey(content)) {

r.setText(params.get(content), 0);

}

}

}

}

}

/**

* .doc文档转html

*

* @param wordFile

* word File对象

* @param htmlFile

* html File对象

*/

private static void wordDocToHtml(File wordFile, File htmlFile) {

if (null == wordFile || null == htmlFile) {

return;

}

File parentFile = htmlFile.getParentFile();

if (!parentFile.exists()) {

parentFile.mkdirs();

}

String absolutePath = parentFile.getAbsolutePath();

HWPFDocument wordDocument;

final String imagepath = absolutePath + "/temp/wordimage/";

try {

// 根据输入文件路径与名称读取文件流

InputStream in = new FileInputStream(wordFile);

// 把文件流转化为输入wordDom对象

wordDocument = new HWPFDocument(in);

// 通过反射构建dom创建者工厂

DocumentBuilderFactory domBuilderFactory = DocumentBuilderFactory

.newInstance();

// 生成dom创建者

DocumentBuilder domBuilder = domBuilderFactory.newDocumentBuilder();

// 生成dom对象

Document dom = domBuilder.newDocument();

// 生成针对Dom对象的转化器

WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(

dom);

// 转化器重写内部方法

wordToHtmlConverter.setPicturesManager(new PicturesManager() {

@Override

public String savePicture(byte[] content,

PictureType pictureType, String suggestedName,

float widthInches, float heightInches) {

File imgPath = new File(imagepath);

if (!imgPath.exists()) {// 图片目录不存在则创建

imgPath.mkdirs();

}

File file = new File(imagepath + suggestedName);

try {

OutputStream os = new FileOutputStream(file);

os.write(content);

os.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return imagepath + suggestedName;

}

});

// 转化器开始转化接收到的dom对象

wordToHtmlConverter.processDocument(wordDocument);

// 保存文档中的图片

List<?> pics = wordDocument.getPicturesTable().getAllPictures();

if (pics != null) {

for (int i = 0; i < pics.size(); i++) {

Picture pic = (Picture) pics.get(i);

try {

pic.writeImageContent(new FileOutputStream(imagepath

+ pic.suggestFullFileName()));

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

}

// 从加载了输入文件中的转换器中提取DOM节点

Document htmlDocument = wordToHtmlConverter.getDocument();

// 从提取的DOM节点中获得内容

DOMSource domSource = new DOMSource(htmlDocument);

// 字节码输出流

OutputStream out = new FileOutputStream(htmlFile);

// 输出流的源头

StreamResult streamResult = new StreamResult(out);

// 转化工厂生成序列转化器

TransformerFactory tf = TransformerFactory.newInstance();

Transformer serializer = tf.newTransformer();

// 设置序列化内容格式

serializer.setOutputProperty(OutputKeys.ENCODING, "Unicode");//此处根据你 的word文档的编码格式进行设置

serializer.setOutputProperty(OutputKeys.INDENT, "yes");

serializer.setOutputProperty(OutputKeys.METHOD, "html");

serializer.transform(domSource, streamResult);

out.close();

in.close();

} catch (FileNotFoundException e1) {

e1.printStackTrace();

} catch (IOException e1) {

e1.printStackTrace();

} catch (TransformerConfigurationException e) {

e.printStackTrace();

} catch (TransformerException e) {

e.printStackTrace();

} catch (ParserConfigurationException e) {

e.printStackTrace();

}

}

/**

* .doc转html

*

* @param wordFilePath

* @param htmlFilePath

*/

private static void wordDocToHtml(String wordFilePath, String htmlFilePath) {

if (mons.lang3.StringUtils.isAnyBlank(wordFilePath,

htmlFilePath)) {

return;

}

File wordFile = new File(wordFilePath);

File htmlFile = new File(htmlFilePath);

wordDocToHtml(wordFile, htmlFile);

}

/**

* html转pdf

*

* @param htmlFile

* @param pdfFile

* @return

* @throws Exception

*/

private static boolean convertHtmlToPdf(File htmlFile, File pdfFile)

throws Exception {

if (null == htmlFile || null == pdfFile) {

logger.info("html转pdf时,有file为空,htmlFile={},pdfFile={}", htmlFile,

pdfFile);

return false;

}

String absoluteFilePath = htmlFile.getParentFile().getAbsolutePath();

if (!pdfFile.getParentFile().exists()) {

pdfFile.getParentFile().mkdirs();

}

// .doc转成的html中有些标签:例如<mate>不严谨,会出现标签不闭合问题,在转pdf时会报异常,故此处用jsoup将html转化成xhtml,将标签严谨化

// 格式化html标签

org.jsoup.nodes.Document parse = Jsoup.parse(htmlFile, "utf-8");

parse.outputSettings()

.syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml)

.escapeMode(Entities.EscapeMode.xhtml);

String html = parse.html();

// 此处将body标签中的字体设置为SimSun,必须是这种样式,才会识别中文支持的文件,如果不设置,会出现转成的pdf中文不显示问题(此处需要替换的字段,可用将自己转成的html打印出来,查看是否是宋体,如不是,将宋体改为你转换成html的字体格式)

html = html.replace("font-family:宋体", "font-family: SimSun");

OutputStream os = new FileOutputStream(pdfFile);

ITextRenderer renderer = new ITextRenderer();

renderer.setDocumentFromString(html);

// 解决中文支持问题

ITextFontResolver fontResolver = renderer.getFontResolver();

String path = Word2PDFUtils.class.getClassLoader()

.getResource("simsun.ttc").getPath();

logger.info(path);

fontResolver.addFont(path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

// 解决图片的相对路径问题

renderer.getSharedContext().setBaseURL(

"file:" + absoluteFilePath + "/temp/htmlimage");

renderer.layout();

renderer.createPDF(os);

os.flush();

os.close();

return true;

}

/**

* html转pdf

*

* @param inputFile

* @param outputFile

* @return

* @throws Exception

*/

private static boolean convertHtmlToPdf(String inputFile, String outputFile)

throws Exception {

if (mons.lang3.StringUtils.isAnyBlank(inputFile,

outputFile)) {

logger.info("html转pdf是,路径为空,inputFile={},outputFile={}", inputFile,

outputFile);

;

return false;

}

File htmlFile = new File(inputFile);

File pdfFile = new File(outputFile);

return convertHtmlToPdf(htmlFile, pdfFile);

}

/**

* 截取pdfFile的第from页至第end页,组成一个新的文件名

*

* @param pdfFile

* 需要分割的PDF

* @param savepath

* 新PDF

* @param from

* 起始页

* @param end

* 结束页

*/

private static void splitPDFFile(String respdfFile, String savepath,

int from, int end) {

com.itextpdf.text.Document document = null;

PdfCopy copy = null;

try {

PdfReader reader = new PdfReader(respdfFile);

int n = reader.getNumberOfPages();

if (end == 0) {

end = n;

}

ArrayList<String> savepaths = new ArrayList<String>();

savepaths.add(savepath);

document = new com.itextpdf.text.Document(reader.getPageSize(1));

copy = new PdfCopy((com.itextpdf.text.Document) document,

new FileOutputStream(savepaths.get(0)));

document.open();

for (int j = from; j < end; j++) {

document.newPage();

PdfImportedPage page = copy.getImportedPage(reader, j);

copy.addPage(page);

}

document.close();

reader.close();

copy.close();

} catch (IOException e) {

e.printStackTrace();

} catch (DocumentException e) {

e.printStackTrace();

}

}

}

其中.doc文档转html方法与其他一样,只是转完html时需要用jsoup转一遍xhtml,使标签严谨化,然后转pdf,转pdf时加入中文字体支持,

如果报没有搜索到方法的异常,可能是jar包版本的问题,就将<!-- <dependency>

<groupId>com.lowagie</groupId>

<artifactId>itext</artifactId>

<version>2.0.8</version>

</dependency> -->依赖放开试试,我开始的时候遇见过这个异常,后来随着导入的依赖增多,这个依赖注掉也不会有这个异常了。可能是其他的依赖里有这个版本--2.0.8的itext的jar包,但是不确定你的其他依赖里是否存在,故此说明

另外附上文件simsun.ttc百度云下载地址:

链接:/s/1iH4iqJB2X_0gB7T4_CClzA

提取码:7rmn

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。