<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      java實現(xiàn)word生成并轉pdf

      前言

      本篇博客主要解決java后臺動態(tài)生成word(docx格式),并將word轉換為pdf并添加水印。

      思考

      項目需求是要導出帶水印的pdf,表格樣式還是有點復雜的,之前考慮過用itextpdf根據(jù)html來生成pdf,但框架用的是前后臺分

      離的,前臺用的是react,并且是在沒有展示出表格的情況下,所以沒法通過前臺獲取html代碼塊生成,后來又自己手動拼接

      html,但代碼量太大,難維護,且樣式不怎么好看。所以決定用freemarker模板生成word,再轉成pdf。翻閱網上很多資料給

      出了很多方案將word轉pdf,有用poi的、有用第三方工具的等等。用poi的寫的都太復雜,jar引用很多,用第三方工具的有局

      限性,不適合夸平臺,需要安裝服務。所以決定用docx4j,但docx4j只支持docx格式的word轉pdf,所以需要freemarker

      生成docx的word。

      動手

      1、pom引入依賴

       
              <dependency>
                  <groupId>com.itextpdf</groupId>
                  <artifactId>itextpdf</artifactId>
                  <version>5.4.3</version>
              </dependency>
      
              <dependency>
                  <groupId>freemarker</groupId>
                  <artifactId>freemarker</artifactId>
                  <version>2.3.23</version>
              </dependency>
      
              <dependency>
                  <groupId>org.docx4j</groupId>
                  <artifactId>docx4j</artifactId>
                  <version>6.1.2</version>
              </dependency>
              <dependency>
                  <groupId>org.docx4j</groupId>
                  <artifactId>docx4j-export-fo</artifactId>
                  <version>6.0.0</version>
              </dependency>    

       

      2、freemarker生成word(docx)

        之前用freemarker生成word的時候都是生成doc格式的,將doc模板文件保存為xml格式再生成word,生成出來的其實是XML文件,

      只不過文件后綴名是doc的,即使在生成的時候將文件后綴名改為docx,生成出來的文件是打不開的。其實docx本質上是個壓縮包,

      里面有包含word主要內容的document.xml文件、資源定義文件document.xml.rels、還有頁眉頁腳文件、圖片資源等等,解決思路是替

      換內容區(qū)的document.xml文件。

      1)、準備docx模板文件,編輯插入占位符。

      2)、將docx文件復制一份,將復制的文件后綴名改為zip

       

      3)、拷貝出zip包里word路徑下的document.xml文件,這個就是word的主內容文件。之前的那個tmp.docx和拷貝出的document.xml

      這兩個文件是我們所需要用到的兩個模板文件,拷貝到項目工程里面去。

       

      4)、工具類代碼

       

        1 package com.eazytec.zqtong.common.utils;
        2 
        3 import com.itextpdf.text.*;
        4 import com.itextpdf.text.pdf.*;
        5 import org.docx4j.Docx4J;
        6 import org.docx4j.convert.out.FOSettings;
        7 import org.docx4j.fonts.IdentityPlusMapper;
        8 import org.docx4j.fonts.Mapper;
        9 import org.docx4j.fonts.PhysicalFonts;
       10 import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
       11 import org.springframework.core.io.ClassPathResource;
       12 
       13 import java.io.*;
       14 import java.util.*;
       15 import java.util.zip.ZipEntry;
       16 import java.util.zip.ZipFile;
       17 import java.util.zip.ZipOutputStream;
       18 
       19 public class PdfUtil {
       20     private static String separator = File.separator;//文件夾路徑分格符
       21 
       22     //=========================================生成申請表pdf===================================
       23 
       24     /**
       25      * freemark生成word----docx格式
       26      * @param dataMap 數(shù)據(jù)源
       27      * @param documentXmlName  document.xml模板的文件名
       28      * @param docxTempName   docx模板的文件名
       29      * @return 生成的文件路徑
       30      */
       31     public static String createApplyPdf(Map<String,Object> dataMap,String documentXmlName,String docxTempName) {
       32         ZipOutputStream zipout = null;//word輸出流
       33         File tempPath = null;//docx格式的word文件路徑
       34         try {
       35             //freemark根據(jù)模板生成內容xml
       36             //================================獲取 document.xml 輸入流================================
       37             ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, documentXmlName, separator + "template" + separator + "downLoad" + separator);
       38             //================================獲取 document.xml 輸入流================================
       39             //獲取主模板docx
       40             ClassPathResource resource = new ClassPathResource("template" + File.separator + "downLoad" + File.separator + docxTempName);
       41             File docxFile = resource.getFile();
       42 
       43             ZipFile zipFile = new ZipFile(docxFile);
       44             Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
       45 
       46             //輸出word文件路徑和名稱
       47             String fileName = "applyWord_" + System.currentTimeMillis() + ".docx";
       48             String outPutWordPath = System.getProperty("java.io.tmpdir").replaceAll(separator + "$", "") + separator + fileName;
       49 
       50             tempPath = new File(outPutWordPath);
       51             //如果輸出目標文件夾不存在,則創(chuàng)建
       52             if (!tempPath.getParentFile().exists()) {
       53                 tempPath.mkdirs();
       54             }
       55             //docx文件輸出流
       56             zipout = new ZipOutputStream(new FileOutputStream(tempPath));
       57 
       58             //循環(huán)遍歷主模板docx文件,替換掉主內容區(qū),也就是上面獲取的document.xml的內容
       59             //------------------覆蓋文檔------------------
       60             int len = -1;
       61             byte[] buffer = new byte[1024];
       62             while (zipEntrys.hasMoreElements()) {
       63                 ZipEntry next = zipEntrys.nextElement();
       64                 InputStream is = zipFile.getInputStream(next);
       65                 if (next.toString().indexOf("media") < 0) {
       66                     zipout.putNextEntry(new ZipEntry(next.getName()));
       67                     if ("word/document.xml".equals(next.getName())) {
       68                         //寫入填充數(shù)據(jù)后的主數(shù)據(jù)信息
       69                         if (documentInput != null) {
       70                             while ((len = documentInput.read(buffer)) != -1) {
       71                                 zipout.write(buffer, 0, len);
       72                             }
       73                             documentInput.close();
       74                         }
       75                     }else {//不是主數(shù)據(jù)區(qū)的都用主模板的
       76                         while ((len = is.read(buffer)) != -1) {
       77                             zipout.write(buffer, 0, len);
       78                         }
       79                         is.close();
       80                     }
       81                 }
       82             }
       83             //------------------覆蓋文檔------------------
       84             zipout.close();//關閉
       85 
       86             //----------------word轉pdf--------------
       87             return convertDocx2Pdf(outPutWordPath);
       88 
       89         } catch (Exception e) {
       90             e.printStackTrace();
       91             try {
       92                 if(zipout!=null){
       93                     zipout.close();
       94                 }
       95             }catch (Exception ex){
       96                 ex.printStackTrace();
       97             }
       98         }
       99         return "";
      100     }
      101 
      102     /**
      103      * word(docx)轉pdf
      104      * @param wordPath  docx文件路徑
      105      * @return  生成的帶水印的pdf路徑
      106      */
      107     public static String convertDocx2Pdf(String wordPath) {
      108         OutputStream os = null;
      109         InputStream is = null;
      110         try {
      111             is = new FileInputStream(new File(wordPath));
      112             WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
      113             Mapper fontMapper = new IdentityPlusMapper();
      114             fontMapper.put("隸書", PhysicalFonts.get("LiSu"));
      115             fontMapper.put("宋體", PhysicalFonts.get("SimSun"));
      116             fontMapper.put("微軟雅黑", PhysicalFonts.get("Microsoft Yahei"));
      117             fontMapper.put("黑體", PhysicalFonts.get("SimHei"));
      118             fontMapper.put("楷體", PhysicalFonts.get("KaiTi"));
      119             fontMapper.put("新宋體", PhysicalFonts.get("NSimSun"));
      120             fontMapper.put("華文行楷", PhysicalFonts.get("STXingkai"));
      121             fontMapper.put("華文仿宋", PhysicalFonts.get("STFangsong"));
      122             fontMapper.put("宋體擴展", PhysicalFonts.get("simsun-extB"));
      123             fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
      124             fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
      125             fontMapper.put("幼圓", PhysicalFonts.get("YouYuan"));
      126             fontMapper.put("華文宋體", PhysicalFonts.get("STSong"));
      127             fontMapper.put("華文中宋", PhysicalFonts.get("STZhongsong"));
      128 
      129             mlPackage.setFontMapper(fontMapper);
      130 
      131             //輸出pdf文件路徑和名稱
      132             String fileName = "pdfNoMark_" + System.currentTimeMillis() + ".pdf";
      133             String pdfNoMarkPath = System.getProperty("java.io.tmpdir").replaceAll(separator + "$", "") + separator + fileName;
      134 
      135             os = new java.io.FileOutputStream(pdfNoMarkPath);
      136 
      137             //docx4j  docx轉pdf
      138             FOSettings foSettings = Docx4J.createFOSettings();
      139             foSettings.setWmlPackage(mlPackage);
      140             Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);
      141 
      142             is.close();//關閉輸入流
      143             os.close();//關閉輸出流
      144 
      145             //添加水印
      146             return addTextMark(pdfNoMarkPath);
      147         } catch (Exception e) {
      148             e.printStackTrace();
      149             try {
      150                 if(is != null){
      151                     is.close();
      152                 }
      153                 if(os != null){
      154                     os.close();
      155                 }
      156             }catch (Exception ex){
      157                 ex.printStackTrace();
      158             }
      159         }finally {
      160             File file = new File(wordPath);
      161             if(file!=null&&file.isFile()&&file.exists()){
      162                 file.delete();
      163             }
      164         }
      165        return "";
      166     }
      167 
      168     /**
      169      * 添加水印圖片
      170      * @param inPdfPath 無水印pdf路徑
      171      * @return 生成的帶水印的pdf路徑
      172      */
      173     private static String addTextMark(String inPdfPath) {
      174         PdfStamper stamp = null;
      175         PdfReader reader = null;
      176         try {
      177             //輸出pdf帶水印文件路徑和名稱
      178             String fileName = "pdfMark_" + System.currentTimeMillis() + ".pdf";
      179             String outPdfMarkPath = System.getProperty("java.io.tmpdir").replaceAll(separator + "$", "") + separator + fileName;
      180 
      181             //添加水印
      182             reader = new PdfReader(inPdfPath, "PDF".getBytes());
      183             stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfMarkPath)));
      184             PdfContentByte under;
      185             int pageSize = reader.getNumberOfPages();// 原pdf文件的總頁數(shù)
      186             //水印圖片
      187             ClassPathResource resource = new ClassPathResource("template" + File.separator + "downLoad" + File.separator + "mark.png");
      188             File file = resource.getFile();
      189             Image image = Image.getInstance(file.getPath());
      190             for (int i = 1; i <= pageSize; i++) {
      191                 under = stamp.getUnderContent(i);// 水印在之前文本下
      192                 image.setAbsolutePosition(100, 210);//水印位置
      193                 under.addImage(image);
      194             }
      195             stamp.close();// 關閉
      196             reader.close();//關閉
      197 
      198             return outPdfMarkPath;
      199         } catch (Exception e) {
      200             e.printStackTrace();
      201             try {
      202                 if (stamp != null) {
      203                     stamp.close();
      204                 }
      205                 if (reader != null) {
      206                     reader.close();//關閉
      207                 }
      208             } catch (Exception ex) {
      209                 ex.printStackTrace();
      210             }
      211         } finally {
      212             //刪除生成的無水印pdf
      213             File file = new File(inPdfPath);
      214             if (file != null && file.exists() && file.isFile()) {
      215                 file.delete();
      216             }
      217         }
      218         return "";
      219     }
      220 
      221     public static void main(String[] args) {
      222 //        createApplyPdf();
      223 //        convert();
      224 //        addTextMark("D:\\test\\test.pdf", "D:\\test\\test2.pdf");
      225     }
      226 
      227 }

       

       

      package com.eazytec.zqtong.common.utils;
      
      
      import freemarker.template.Configuration;
      import freemarker.template.Template;
      
      import java.io.*;
      import java.util.Map;
      
      /**
       * 獲取freemarker模板字符串
       */
      public class FreeMarkUtils {
      
          /**
           * 獲取模板字符串
           * @param dataMap   參數(shù)
           * @param templateName  模板名稱
           * @param temp_path  模板路徑 classes下的路徑 如果  classes/templates  傳入 /templates即可
           * @return
           */
          public static String getFreemarkerContent(Map dataMap, String templateName, String temp_path) {
              String result = "";
              try {
                  //創(chuàng)建配置實例
                  Configuration configuration = new Configuration();
      
                  //設置編碼
                  configuration.setDefaultEncoding("UTF-8");
      
                  configuration.setClassForTemplateLoading(FreeMarkUtils.class, temp_path);
                  //獲取模板
                  Template template = configuration.getTemplate(templateName);
      
                  StringWriter swriter = new StringWriter();
                  //生成文件
                  template.process(dataMap, swriter);
                  result = swriter.toString();
      
      
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return result;
          }
      
          /**
           * 生成主數(shù)據(jù)模板xml
           *
           * @param dataMap      數(shù)據(jù)參數(shù)
           * @param templateName 模板名稱 eg: xxx.xml
           * @param pathPrefix   模板路徑 eg: /templates/
           * @param filePath     生成路徑 eg: d:/ex/ee/xxx.xml
           */
          public static void createTemplateXml(Map dataMap, String templateName, String pathPrefix, String filePath) {
              try {
                  //創(chuàng)建配置實例
                  Configuration configuration = new Configuration();
      
                  //設置編碼
                  configuration.setDefaultEncoding("UTF-8");
      
                  //ftl模板文件統(tǒng)一放至 com.lun.template 包下面
      //            configuration.setDirectoryForTemplateLoading(new File("D:/idea_workspace/alarm/alarm/src/main/resources/template/"));
      //            configuration.setClassForTemplateLoading(FreemarkerWordUtils.class,"/template/doc");
                  configuration.setClassForTemplateLoading(FreeMarkUtils.class, pathPrefix);
                  //獲取模板
                  Template template = configuration.getTemplate(templateName);
      //            System.out.println("filePath ==> " + filePath);
                  //輸出文件
                  File outFile = new File(filePath);
      //            System.out.println("outFile.getParentFile() ==> " + outFile.getParentFile());
                  //如果輸出目標文件夾不存在,則創(chuàng)建
                  if (!outFile.getParentFile().exists()) {
                      outFile.getParentFile().mkdirs();
                  }
      
                  //將模板和數(shù)據(jù)模型合并生成文件
                  Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
      
      
                  //生成文件
                  template.process(dataMap, out);
      
                  //關閉流
                  out.flush();
                  out.close();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
          /**
           * 獲取模板字符串輸入流
           * @param dataMap   參數(shù)
           * @param templateName  模板名稱
           * @param tempPath  模板路徑 classes下的路徑 如果  classes/templates  傳入 /templates即可
           * @return
           */
          public static ByteArrayInputStream getFreemarkerContentInputStream(Map dataMap, String templateName, String tempPath) {
              ByteArrayInputStream in = null;
      
              try {
                  //創(chuàng)建配置實例
                  Configuration configuration = new Configuration();
      
                  //設置編碼
                  configuration.setDefaultEncoding("UTF-8");
      
                  //ftl模板文件統(tǒng)一放至 com.lun.template 包下面
      //            configuration.setDirectoryForTemplateLoading(new File("D:/idea_workspace/alarm/alarm/src/main/resources/template/"));
                  configuration.setClassForTemplateLoading(FreeMarkUtils.class, tempPath);
                  //獲取模板
                  Template template = configuration.getTemplate(templateName);
      
                  StringWriter swriter = new StringWriter();
                  //生成文件
                  template.process(dataMap, swriter);
                  String result = swriter.toString();
                  in = new ByteArrayInputStream(swriter.toString().getBytes());
      
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return in;
          }
      }

       

       

       

      問題

      生成文件下載的時候感覺稍微有點慢,其實文件不大,有個8、9秒的樣子才會有下載框出現(xiàn),不知道是不是前后臺分離的原因。

       

       

       

      posted @ 2019-07-19 09:33  顏色不一樣的煙火  閱讀(22474)  評論(10)    收藏  舉報
      主站蜘蛛池模板: 亚洲欧美日韩愉拍自拍美利坚| 蜜芽久久人人超碰爱香蕉| 国产精品会所一区二区三区| 国产乱女乱子视频在线播放| 欧洲国产成人久久精品综合| 久久亚洲精品情侣| 97视频精品全国免费观看| 国产伦精品一区二区亚洲| 亚洲色欲色欱WWW在线| 久久精品国产91精品亚洲| 美日韩av一区二区三区| 精品国产AV最大网站| 曰本丰满熟妇xxxx性| 乱人伦人妻中文字幕不卡| 国产成人精品无码专区| 精品中文字幕人妻一二| 成人无码午夜在线观看| 欧美性69式xxxx护士| 久久久久国产精品熟女影院| 国产仑乱无码内谢| 亚洲午夜久久久久久噜噜噜| 老色鬼永久精品网站| 久久久一本精品99久久精品88| 乱人伦中文视频在线| 国产精品亚洲二区在线看| 日韩中文日韩中文字幕亚| 国产亚洲人成网站在线观看| 中国少妇人妻xxxxx| 日本亲近相奷中文字幕| 尤物国精品午夜福利视频| 国产91特黄特色A级毛片| 久久亚洲欧美日本精品| 东方四虎av在线观看| 中文字幕少妇人妻精品| 高清欧美性猛交xxxx黑人猛交| 精品久久精品久久精品九九| 欧美极品色午夜在线视频| 日韩乱码人妻无码中文字幕视频| 丰满岳乱妇久久久| 欧美性猛交xxxx乱大交丰满 | 中文字幕乱码一区二区免费|