如何使用freeMarker生成doc、docx文档
如何使用freeMarker生成doc、docx、pdf文件
freeMarker是什么
doc和docx有什么區(qū)別
如何生成doc文檔(帶圖片)
如何生成docx文檔,以及將其生成pdf文檔
freeMarker是什么
http://freemarker.foofun.cn/
doc和docx有什么區(qū)別
格式不同
DOCX是WORD2007及以上版的格式,是一種基于XML的壓縮格式。
DOC是WORD2003及以下版的格式。
體積不同,docx遠大于doc
doc是單個文件,而docx其實是由一個zip壓縮文件更改后綴而來
如何生成doc文檔
由1可以明白freemarker可以輸出文本信息, 而我們的doc其實就是一個文本,所以可以直接使用freemarker可以doc文件,將doc文件,另存為xml文件,修改成動態(tài)數(shù)據(jù)模板,如果帶有圖片,可直接由圖片轉成base64格式,再按照普通屬性進行替換(此處我們重點說生成docx文檔,因為生成pdf文檔,poi對freemark生成的doc文檔轉成pdf無法辨識)
如何生成docx文檔,以及將其生成pdf文檔
docx是一個zip壓縮文件,解壓后的內容如下:
主要關注:document.xml (文檔結構),document.xml.rels(圖片引用關系配置),以及media(存放圖片的目錄)目錄
還是直接上代碼吧
首先寫一個要生成的docx樣式,修改后綴為zip,然后將其解壓,設置動態(tài)數(shù)據(jù),修改document.xml 和document.xml.rels文件按照freeMarker數(shù)據(jù)格式編寫
document.xml (文檔結構,橘色部分freemarker需要設置的動態(tài)數(shù)據(jù)):
文檔結構,橘色部分freemarker引用document.xml.rels中的id:
document.xml.rels(圖片引用關系配置,橘色部分freemarker需要動態(tài)生成的圖片引用id)
依賴jar
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version></dependency><dependency><groupId>com.artofsolving</groupId><artifactId>jodconverter-maven-plugin</artifactId><version>2.2.1</version></dependency <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>org.apache.poi.xwpf.converter.core</artifactId><version>1.0.5</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>org.apache.poi.xwpf.converter.pdf</artifactId><version>1.0.5</version></dependency> public class XMlToDocx {private static String OS = System.getProperty("os.name").toLowerCase();/*** 根據(jù)數(shù)據(jù)生成文本* @param dataMap 數(shù)據(jù)* @param outFilePath 生成的document.xml和document.xml.rels對應的目錄名稱* @param template 模板對象* @throws Exception*/private static void toText(Map<String,Object> dataMap,String outFilePath,Template template)throws Exception {File docFile = new File(outFilePath);FileOutputStream fos = new FileOutputStream(docFile);Writer out = new BufferedWriter(new OutputStreamWriter(fos),10240);template.process(dataMap,out);if(out != null){out.close();}}/*** 生成word docx* @param dataMap 數(shù)據(jù)* @param ftlPath ftl存放的目錄(模板)* @param docFilePath 生成的document.xml和document.xml.rels對應的目錄名稱* @param fileList fileList 圖片文件* @throws Exception*/public static void makeWord(Map<String,Object> dataMap,String ftlPath,String docFilePath, List<File> fileList) throws Exception {/** 初始化配置文件 **/Configuration configuration = new Configuration();String fileDirectory = ftlPath;/** 加載文件 **/configuration.setDirectoryForTemplateLoading(new File(fileDirectory));/** 加載模板 **/Template template = configuration.getTemplate("document.xml");/** 指定輸出word文件的路徑 **/String outFilePath = docFilePath+".xml";toText(dataMap,outFilePath,template);template = configuration.getTemplate("document.xml.rels");outFilePath = docFilePath+".xml.rels";toText(dataMap,outFilePath,template);try {ZipInputStream zipInputStream = ZipUtils.wrapZipInputStream(new FileInputStream(new File(fileDirectory+File.separator+"report.zip")));//該zip文件是docx重命名后的壓縮文件ZipOutputStream zipOutputStream = ZipUtils.wrapZipOutputStream(new FileOutputStream(new File(docFilePath+".docx")));File fileText = new File(docFilePath+".xml");File fileImg = new File(docFilePath+".xml.rels");ZipUtils.replaceItem(zipInputStream, zipOutputStream, new FileInputStream(fileText), new FileInputStream(fileImg),fileList);if(fileText.exists()){fileText.delete();}if(fileImg.exists()){fileImg.delete();}} catch (Exception e) {System.out.println(e.toString());}}/*** 生成pdf*/public static void makePdfByXcode(String ftlPath,String docFilePath){try {XWPFDocument document=new XWPFDocument(new FileInputStream(new File(docFilePath+".docx")));File outFile=new File(docFilePath+".pdf");if(!outFile.getParentFile().exists()){outFile.getParentFile().mkdirs();}OutputStream out=new FileOutputStream(outFile);PdfOptions options= PdfOptions.getDefault();IFontProvider iFontProvider = new IFontProvider() {@Overridepublic Font getFont(String familyName, String encoding, float size, int style, Color color) {try {BaseFont bfChinese = null;if( OS.indexOf("linux")>=0){bfChinese = BaseFont.createFont(ftlPath+"/font/msyh.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);}else{bfChinese = BaseFont.createFont("C:/WINDOWS/Fonts/STSONG.TTF", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);}Font fontChinese = new Font(bfChinese, size, style, color);if (familyName != null)fontChinese.setFamily(familyName);return fontChinese;} catch (Exception e) {e.printStackTrace();return null;}}};options.fontProvider( iFontProvider );PdfConverter.getInstance().convert(document,out,options);}catch ( Exception e) {e.printStackTrace();}}} public class ZipUtils {private static String docText = "word/document.xml";//要替換的document.xml的位置private static String imgName = "word/_rels/document.xml.rels"; //要替換的document.xml.rels的位置private static String mediaName = "word/media/";//圖片meida的位置/**** @param zipInputStream zip文件的zip輸入流* @param zipOutputStream 輸出的zip輸出流* @param docTextInputStream 替換后的document.xml文本* @param imgInputStream 替換后的document.xml.rels文本* @param fileList 需要壓入meida的圖片*/public static void replaceItem(ZipInputStream zipInputStream,ZipOutputStream zipOutputStream,InputStream docTextInputStream,InputStream imgInputStream, List<File> fileList){//if(null == zipInputStream){return;}if(null == zipOutputStream){return;}if(null == docTextInputStream){return;}boolean replaceMedia = false;//ZipEntry entryIn;try {while((entryIn = zipInputStream.getNextEntry())!=null){String entryName = entryIn.getName();ZipEntry entryOut = new ZipEntry(entryName);// 只使用 namezipOutputStream.putNextEntry(entryOut);// 緩沖區(qū)byte [] buf = new byte[8*1024];int len;if(entryName.equals(docText)){// 使用替換流(替換文字內容)while((len = (docTextInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}}else if(entryName.equals( imgName)){// 使用替換流(替換圖片)while((len = (imgInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}}else if(entryName.contains(mediaName)&&replaceMedia){}else if(entryName.contains(mediaName)&&!entryName.equals(mediaName)&&!replaceMedia){//將圖片壓縮到media目錄中replaceMedia = true;if(entryName.contains("image1.png")){// 輸出普通Zip流while((len = (zipInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}// 關閉此 entryzipOutputStream.closeEntry();}for(int i=0;i<fileList.size();i++){entryIn = new ZipEntry(mediaName+fileList.get(i).getName());zipOutputStream.putNextEntry(entryIn);FileInputStream in = null;try {in = new FileInputStream(fileList.get(i));while ((len = in.read(buf)) != -1){zipOutputStream.write(buf, 0, len);}// 關閉此 entryzipOutputStream.closeEntry();} catch (IOException e) {}finally {close(in);}}}else {// 輸出普通Zip流while((len = (zipInputStream.read(buf))) > 0) {zipOutputStream.write(buf, 0, len);}}// 關閉此 entryzipOutputStream.closeEntry();}} catch (IOException e) {e.printStackTrace();}finally {//e.printStackTrace();close(docTextInputStream);close(zipInputStream);close(zipOutputStream);close(imgInputStream);}}/*** 包裝輸入流*/public static ZipInputStream wrapZipInputStream(InputStream inputStream){ZipInputStream zipInputStream = new ZipInputStream(inputStream);return zipInputStream;}/*** 包裝輸出流*/public static ZipOutputStream wrapZipOutputStream(OutputStream outputStream){ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);return zipOutputStream;}private static void close(InputStream inputStream){if (null != inputStream){try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}private static void close(OutputStream outputStream){if (null != outputStream){try {outputStream.flush();outputStream.close();} catch (IOException e) {e.printStackTrace();}}} }加入以上class,按照自己指定的數(shù)據(jù)格式傳入數(shù)據(jù),則可生成docx和pdf文檔
遇到的坑:
1、未理解docx,其實就是一個壓縮zip文件,將其中需要替換的內容,替換后,重新生成一個docx文檔就可以
2、docx如果有表格樣式的動態(tài)內容循環(huán),修改成模板后,重新壓縮,修改后綴為docx不能打開,所以遇到表格樣式的動態(tài)內容循環(huán),盡量小心一些
3、資料太少,無處尋求幫組
第一次寫博客哈,寫的不好,希望大家多多提意見,希望對需要的朋友有幫組
總結
以上是生活随笔為你收集整理的如何使用freeMarker生成doc、docx文档的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tcpdump 命令详解
- 下一篇: java中如何定义一个_java中如何定