最近項目有個需求,大致流程是前端保存富文本(html的代碼)到數據庫,后臺需要將富文本代碼轉成帶格式的文字,插入到word模板里,然后將word轉成pdf,再由前端調用接口下載pdf文件!
1、思路
這里的主要難點就是將html的格式帶入到word里,所以這里要先將格式寫入到html里。怎么寫入到html里呢?這里提供一下思路,就是把你的word模板先轉成html代碼,為啥是代碼不是html文件呢?因為我要用這個html代碼去把富文本插進去,怎么插呢?首先要標記一個替換符在word模板里,這里有了替換符我們就可以用replace把富文本代碼替換掉這個替換符,這樣富文本就插進去了嘛!然后再把html代碼轉成word文檔,再進行你的邏輯操作就可以了!
總結: 大致意思就是將word模板提取成html代碼,再把富文本替換進去,然后把替換完的代碼轉成word。
2、依賴
主要就是用的aspose-words,因為好用所以一直在用,這里用aspose主要是文件的轉換。我的業務邏輯需要把數據放到word指定的位置里,所以我要用替換的方式去替換數據,這里也用到了poi-tl。
貼一下我的版本,這里的aspose我是放到lib里了
依賴想下載的直接去下載:https://download.csdn.net/download/weixin_44953395/88565563
不要積分的
<!-- word轉pdf-->
<dependency><groupId>com.aspose</groupId><artifactId>aspose-words</artifactId><version>15.8.0</version><scope>system</scope><systemPath>${project.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
<!--poi-tl-->
<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.10.4</version>
</dependency>
3、代碼
說了一堆廢話,還是得看代碼,誰也擋不住復制粘貼!
@Test
public void testDocToHtml() {String html = WordToPdfUtil.parseWord2Html("D:\\environment\\idea\\company\\ceshi\\test.docx");String fwb = "<ol><li>古詩</li></ol><p>《南歌子·似帶如絲柳》</p><p><span style=\"color: rgb(212, 56, 13);\"><u>唐·溫庭筠</u></span></p><p><span style=\"background-color: rgb(115, 209, 61);\">似帶如絲柳,團酥握雪花。</span></p><p><span style=\"color: rgb(89, 126, 247);\">簾卷玉鉤斜,九衢塵欲暮,逐香車。</span></p>";assert html != null;String fwbHtml = html.replaceAll("Fwb1", fwb);System.out.println(fwbHtml);WordToPdfUtil.htmlToWord(fwbHtml.getBytes(StandardCharsets.UTF_8), 20, "D:\\environment\\idea\\company\\ceshi\\ceshi.docx");
}
package com.byqh.utils;import com.aspose.words.*;import java.io.*;
import java.nio.charset.StandardCharsets;/*** word轉Pdf幫助類* <p>* 備注:需要引入 aspose-words-15.8.0-jdk16.jar*/
public class WordToPdfUtil {private static boolean getLicense() {boolean result = false;try {InputStream is = WordToPdfUtil.class.getClassLoader().getResourceAsStream("license.xml");License asposeLic = new License();asposeLic.setLicense(is);result = true;} catch (Exception e) {e.printStackTrace();}return result;}/*** word轉pdf* * @param wordPath 需要被轉換的word全路徑帶文件名* @param pdfPath 轉換之后pdf的全路徑帶文件名*/public static void docToPdf(String wordPath, String pdfPath) {// 驗證License 若不驗證則轉化出的pdf文檔會有水印產生if (!getLicense()) {return;}try {long old = System.currentTimeMillis();//新建一個pdf文檔File file = new File(pdfPath);FileOutputStream os = new FileOutputStream(file);//wordPath是將要被轉化的word文檔Document doc = new Document(wordPath);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互轉換doc.save(os, SaveFormat.PDF);long now = System.currentTimeMillis();os.close();//轉化用時System.out.println("共耗時:" + ((now - old) / 1000.0) + "秒");} catch (Exception e) {e.printStackTrace();}}/*** word轉html文本** @param wordPath 需要轉換的doc文件* @return html代碼*/public static String parseWord2Html(String wordPath) {// 驗證License 若不驗證則轉化出的pdf文檔會有水印產生if (!getLicense()) {return null;}HtmlSaveOptions saveOptions = new HtmlSaveOptions();saveOptions.setExportHeadersFootersMode(ExportHeadersFootersMode.NONE); ByteArrayOutputStream htmlStream = new ByteArrayOutputStream();String htmlText = "";try {Document doc = new Document(wordPath);doc.save(htmlStream, saveOptions);htmlText = new String(htmlStream.toByteArray(), StandardCharsets.UTF_8);htmlStream.close();} catch (Exception e) {System.out.println(e.getMessage());}return htmlText;}/*** html字節數組轉word字節數組** @param content html字節數組* @param toType 值為SaveFormat.DOCX-20或SavaFormat.Doc-10對應的值* @param filePath 轉換完成之后的文件路徑*/public static void htmlToWord(byte[] content, Integer toType, String filePath) {// 驗證License 若不驗證則轉化出的pdf文檔會有水印產生if (!getLicense()) {return;}try {File file = new File(filePath);FileOutputStream os = new FileOutputStream(file);InputStream is = new ByteArrayInputStream(content);Document doc = new Document();DocumentBuilder builder = new DocumentBuilder(doc);InputStreamReader streamReader = new InputStreamReader(is, StandardCharsets.UTF_8);BufferedReader reader = new BufferedReader(streamReader);String line;StringBuilder html = new StringBuilder();while ((line = reader.readLine()) != null) {html.append(line);}reader.close();builder.insertHtml(String.valueOf(html));doc.save(os, toType);System.out.println("html轉word成功!");} catch (Exception e) {System.out.println(e.getMessage());}}}
效果:
替換之前:(這里的Fwb1就是一個標志符)
替換之后:
這里的富文本是用的wangeditor,網站是:https://www.wangeditor.com/
寫在富文本的樣子是下圖這樣的,總體來說還可以!
4、替換
替換用的是poi-tl,它的網址說明文檔:http://deepoove.com/
@Test
public void testDocTh() throws IOException {Map<String, Object> map = new HashMap<>();map.put("sj01", "測試-test01");map.put("sj02", "測試-test02");List<PictureRenderData> list = new ArrayList<>();//這里的size設置的是寬和高list.add(Pictures.ofStream(new FileInputStream("D:\\environment\\idea\\company\\ceshi\\400X350.png")).size(400, 350).create());list.add(Pictures.ofStream(new FileInputStream("D:\\environment\\idea\\company\\ceshi\\400X400.png")).size(400, 400).create());for (int i = 0; i < list.size(); i++) {map.put("tp0" + (i + 1), list.get(i));}XWPFTemplate template = XWPFTemplate.compile("D:\\environment\\idea\\company\\ceshi\\test.docx").render(map);FileOutputStream out1 = new FileOutputStream("D:\\environment\\idea\\company\\ceshi\\out_template.docx");template.write(out1);out1.close();
}
替換之前:
替換之后:
說明一下,這里的兩張圖片一個是400X350的一個是400X400的兩個大小差不太多,所以大小不太明顯!