當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
SpringBoot word文档转pdf
生活随笔
收集整理的這篇文章主要介紹了
SpringBoot word文档转pdf
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一.背景
項(xiàng)目中有個(gè)需求大體意思是,上傳一個(gè)word模板,根據(jù)word模板合成word文件,再將word文件轉(zhuǎn)為pdf。
二.方案選擇
Spire.Doc for Java方案
Spire.Doc for Java這個(gè)是商用收費(fèi)的,不過API文檔豐富且集成簡單,免費(fèi)版僅支持3頁轉(zhuǎn)換。類似的還有ITEXT,這個(gè)商用也是受限制的。
docx4j方案
開源可商用,僅支持docx格式的word。
jodconverter+LibreOffice 方案
開源可商用,調(diào)用本地office服務(wù),進(jìn)行pdf轉(zhuǎn)換,類似的還有jodconverter+openOffice。
其他
至于其他的由于不支持跨平臺(tái)不做考慮。
三.實(shí)操
1.docx4j
首先嘗試了docx4j,因?yàn)閐ocx4j本身支持模板替換的操作,可一次性做替換及文檔類型轉(zhuǎn)換,而且僅支持docx類型,對于本次需求問題不大。
清除工具類,用于處理占位符替換不生效的問題,這里參考文章
public class DocxVariableClearUtil {/*** 去任意XML標(biāo)簽*/private static final Pattern XML_PATTERN = Pattern.compile("<[^>]*>");private DocxVariableClearUtil() {}/*** start符號*/private static final char PREFIX = '$';/*** 中包含*/private static final char LEFT_BRACE = '{';/*** 結(jié)尾*/private static final char RIGHT_BRACE = '}';/*** 未開始*/private static final int NONE_START = -1;/*** 未開始*/private static final int NONE_START_INDEX = -1;/*** 開始*/private static final int PREFIX_STATUS = 1;/*** 左括號*/private static final int LEFT_BRACE_STATUS = 2;/*** 右括號*/private static final int RIGHT_BRACE_STATUS = 3;/*** doCleanDocumentPart** @param wmlTemplate* @param jc* @return* @throws JAXBException*/public static Object doCleanDocumentPart(String wmlTemplate, JAXBContext jc) throws JAXBException {// 進(jìn)入變量塊位置int curStatus = NONE_START;// 開始位置int keyStartIndex = NONE_START_INDEX;// 當(dāng)前位置int curIndex = 0;char[] textCharacters = wmlTemplate.toCharArray();StringBuilder documentBuilder = new StringBuilder(textCharacters.length);documentBuilder.append(textCharacters);// 新文檔StringBuilder newDocumentBuilder = new StringBuilder(textCharacters.length);// 最后一次寫位置int lastWriteIndex = 0;for (char c : textCharacters) {switch (c) {case PREFIX:// 不管其何狀態(tài)直接修改指針,這也意味著變量名稱里面不能有PREFIXkeyStartIndex = curIndex;curStatus = PREFIX_STATUS;break;case LEFT_BRACE:if (curStatus == PREFIX_STATUS) {curStatus = LEFT_BRACE_STATUS;}break;case RIGHT_BRACE:if (curStatus == LEFT_BRACE_STATUS) {// 接上之前的字符newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex, keyStartIndex));// 結(jié)束位置int keyEndIndex = curIndex + 1;// 替換String rawKey = documentBuilder.substring(keyStartIndex, keyEndIndex);// 干掉多余標(biāo)簽String mappingKey = XML_PATTERN.matcher(rawKey).replaceAll("");if (!mappingKey.equals(rawKey)) {char[] rawKeyChars = rawKey.toCharArray();// 保留原格式StringBuilder rawStringBuilder = new StringBuilder(rawKey.length());// 去掉變量引用字符for (char rawChar : rawKeyChars) {if (rawChar == PREFIX || rawChar == LEFT_BRACE || rawChar == RIGHT_BRACE) {continue;}rawStringBuilder.append(rawChar);}// 要求變量連在一起String variable = mappingKey.substring(2, mappingKey.length() - 1);int variableStart = rawStringBuilder.indexOf(variable);if (variableStart > 0) {rawStringBuilder = rawStringBuilder.replace(variableStart, variableStart + variable.length(), mappingKey);}newDocumentBuilder.append(rawStringBuilder.toString());} else {newDocumentBuilder.append(mappingKey);}lastWriteIndex = keyEndIndex;curStatus = NONE_START;keyStartIndex = NONE_START_INDEX;}default:break;}curIndex++;}// 余部if (lastWriteIndex < documentBuilder.length()) {newDocumentBuilder.append(documentBuilder.substring(lastWriteIndex));}return XmlUtils.unmarshalString(newDocumentBuilder.toString(), jc);}}2.poi-tl+jodconverter+LibreOffice 方案
poi-tl這個(gè)是專門用來進(jìn)行word模板合成的開源庫,文檔很詳細(xì)。
LibreOffice 下載最新的穩(wěn)定版本即可。
JodConverterConfig配置類
yml配置文件
jodconverter:local:enabled: trueoffice-home: "C:\\Program Files\\LibreOffice"PdfService合成導(dǎo)出代碼
@Slf4j @Component public class PdfService {@Autowiredprivate DocumentConverter documentConverter;public void docxToPDF(InputStream inputStream,HttpServletResponse response,String fileName) {response.setContentType("application/pdf");try {String fullFileName = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);response.setHeader("Content-disposition","attachment;filename=\\"+fullFileName+".pdf\\");documentConverter.convert(inputStream).as(DefaultDocumentFormatRegistry.DOCX).to(response.getOutputStream()).as(DefaultDocumentFormatRegistry.PDF).execute();} catch (OfficeException |IOException e) {log.error("word轉(zhuǎn)pdf失敗:{}",e.getMessage());}}public void exportByLocalPath(HttpServletResponse response, String fileName, String path, Object params) throws Exception {BufferedOutputStream outputStream = null;BufferedInputStream wordInputStream = null;try (InputStream in = PdfService.class.getClassLoader().getResourceAsStream(path)) {// 生成臨時(shí)文件String outPutWordPath = System.getProperty("java.io.tmpdir").replaceAll(File.separator + "$", "") + fileName+".docx";File tempFile = FileUtil.touch(outPutWordPath);outputStream = FileUtil.getOutputStream(tempFile);// word模板合成寫到臨時(shí)文件WordUtil.replaceWord(outputStream, in, params);// word 轉(zhuǎn)pdfwordInputStream = FileUtil.getInputStream(tempFile);docxToPDF(wordInputStream, response,fileName);// 移除臨時(shí)文件FileUtil.del(tempFile);} catch (Exception e) {log.error("docx文檔轉(zhuǎn)換為PDF失敗", e.getMessage());} finally {IoUtil.close(outputStream);IoUtil.close(wordInputStream);}}四.結(jié)論
1.docx4j方案
- 依賴少
- 同時(shí)支持word合成及格式轉(zhuǎn)換
- 轉(zhuǎn)化效率較差
- 對于含樣式及圖片轉(zhuǎn)換不友好,容易排版混亂
2.jodconverter+LibreOffice 方案
- 操作穩(wěn)定
- 轉(zhuǎn)換效率快
- 集成依賴設(shè)置較多
- 依賴本地服務(wù)
- LibreOffice打開word可能排版樣式錯(cuò)亂
最后考慮項(xiàng)目需求,最終選擇了jodconverter+LibreOffice方案。
總結(jié)
以上是生活随笔為你收集整理的SpringBoot word文档转pdf的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开发一个程序基本思路
- 下一篇: x64枚举DPC定时器