Docx4j實現(xiàn)Word轉(zhuǎn)Pdf

此例通過docx4j實現(xiàn)word轉(zhuǎn)成pdf元咙。
因功能較簡單君纫,只在此展示一下后臺功能代碼譬猫。
1.公用方法類

package com.ldht.common.util.wordPdf;

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.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.docx4j.convert.out.pdf.PdfConversion;
import org.docx4j.convert.out.pdf.viaXSLFO.PdfSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.AlternativeFormatInputPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.CTAltChunk;

/**
 * @author HMZ
 */
public class WordUtil {
    public void mergeDocx(HttpServletResponse response,List<String> list){  
        List<InputStream>  inList=new ArrayList<InputStream>();  
          for(int i=0;i<list.size();i++)  
            try {  
                inList.add(new FileInputStream(list.get(i)));  
            } catch (FileNotFoundException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
          try {  
            InputStream inputStream=mergeDocx(inList);  
            saveTemplate(response,inputStream);  
        } catch ( IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (Docx4JException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
    }  
      
    public InputStream mergeDocx(final List<InputStream> streams)  throws Docx4JException, IOException {    
    
        WordprocessingMLPackage target = null;    
        final File generated = File.createTempFile("generated", ".docx");    
    
        int chunkId = 0;    
        Iterator<InputStream> it = streams.iterator();    
        while (it.hasNext()) {    
            InputStream is = it.next();    
            if (is != null) {    
                if (target == null) {    
                    // Copy first (master) document    
                    OutputStream os = new FileOutputStream(generated);    
                    os.write(IOUtils.toByteArray(is));    
                    os.close();    
        
                    target = WordprocessingMLPackage.load(generated);    
                } else {    
                    // Attach the others (Alternative input parts)    
                    insertDocx(target.getMainDocumentPart(),    
                            IOUtils.toByteArray(is), chunkId++);    
                }    
            }    
        }    
        
        if (target != null) {    
            target.save(generated);    
            FileInputStream input = new FileInputStream(generated);
            //獲取docx解析對象
//            XWPFDocument document = new XWPFDocument(target);
            return new FileInputStream(generated);    
        } else {    
            return null;    
        }    
    }    
    
    // 插入文檔    
    private void insertDocx(MainDocumentPart main, byte[] bytes, int chunkId) {    
        try {    
            AlternativeFormatInputPart afiPart = new AlternativeFormatInputPart(    
                    new PartName("/part" + chunkId + ".docx"));    
         //   afiPart.setContentType(new ContentType(CONTENT_TYPE));    
            afiPart.setBinaryData(bytes);    
            Relationship altChunkRel = main.addTargetPart(afiPart);    
        
            CTAltChunk chunk = Context.getWmlObjectFactory().createCTAltChunk();    
            chunk.setId(altChunkRel.getId());    
        
            main.addObject(chunk);    
        } catch (Exception e) {    
            e.printStackTrace();    
        }    
    }                                    
  
    public  void saveTemplate(HttpServletResponse response,InputStream fis) throws IOException{  
        OutputStream fos = response.getOutputStream();  
        int bytesum = 0;     
        int byteread = 0;  
        try {  
            byte[] buffer = new byte[10240];   
            while ( (byteread = fis.read(buffer)) != -1) {     
                bytesum += byteread; //字節(jié)數(shù) 文件大小    
                fos.write(buffer, 0, byteread);     
            }     
            fis.close();   
            fos.close();  
        } catch (FileNotFoundException e1) {  
            e1.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
    
    /** 
     * docx文檔轉(zhuǎn)換為PDF 
     * @param docx docx文檔 
     * @param pdfPath PDF文檔存儲路徑 
     * @throws Exception 可能為Docx4JException, FileNotFoundException, IOException等 
     */  
    @SuppressWarnings("deprecation")
    public void convertDocxToPDF(File docx, String pdfPath) throws Exception {  
        OutputStream os = null;  
        try {  
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(docx);  
//            Mapper fontMapper = new BestMatchingMapper();   
            Mapper fontMapper = new IdentityPlusMapper();  
            //中文字體轉(zhuǎn)換
            fontMapper.getFontMappings().put("華文行楷", PhysicalFonts.getPhysicalFonts().get("STXingkai"));  
            fontMapper.getFontMappings().put("隸書", PhysicalFonts.getPhysicalFonts().get("LiSu"));
            fontMapper.getFontMappings().put("宋體",PhysicalFonts.getPhysicalFonts().get("SimSun"));
            fontMapper.getFontMappings().put("微軟雅黑",PhysicalFonts.getPhysicalFonts().get("Microsoft Yahei"));
            fontMapper.getFontMappings().put("黑體",PhysicalFonts.getPhysicalFonts().get("SimHei"));
            fontMapper.getFontMappings().put("楷體",PhysicalFonts.getPhysicalFonts().get("KaiTi"));
            fontMapper.getFontMappings().put("新宋體",PhysicalFonts.getPhysicalFonts().get("NSimSun"));
            fontMapper.getFontMappings().put("華文行楷", PhysicalFonts.getPhysicalFonts().get("STXingkai"));
            fontMapper.getFontMappings().put("華文仿宋", PhysicalFonts.getPhysicalFonts().get("STFangsong"));
            fontMapper.getFontMappings().put("宋體擴展",PhysicalFonts.getPhysicalFonts().get("simsun-extB"));
            fontMapper.getFontMappings().put("仿宋",PhysicalFonts.getPhysicalFonts().get("FangSong"));
            fontMapper.getFontMappings().put("仿宋_GB2312",PhysicalFonts.getPhysicalFonts().get("FangSong_GB2312"));
            fontMapper.getFontMappings().put("幼圓",PhysicalFonts.getPhysicalFonts().get("YouYuan"));
            fontMapper.getFontMappings().put("華文宋體",PhysicalFonts.getPhysicalFonts().get("STSong"));
            fontMapper.getFontMappings().put("華文中宋",PhysicalFonts.getPhysicalFonts().get("STZhongsong"));
            mlPackage.setFontMapper(fontMapper);  
      
            PdfConversion conversion = new org.docx4j.convert.out.pdf.viaXSLFO.Conversion(mlPackage);  
            os = new FileOutputStream(pdfPath);  
             
            conversion.output(os, new PdfSettings());  
        } finally {  
            IOUtils.closeQuietly(os);  
        }  
    }  
    
    /**
     * 將文件內(nèi)容寫入到臨時文件中
     * @param inputUrl
     * @param file
     * @throws IOException
     */
    public void createFile(String inputUrl,File file) throws IOException{
         //獲取docx解析對象
        XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
        FileOutputStream stream = new FileOutputStream(file);
        document.write(stream);
        stream.close();
    }
    
    /**
     * 替換文本
     * @param document docx解析對象
     */
    public static void changeText(XWPFDocument document, String oldValue, String newValue){
        //獲取段落集合
        List<XWPFParagraph> paragraphs = document.getParagraphs();

        for (XWPFParagraph paragraph : paragraphs) {
            //判斷此段落時候需要進行替換
            String text = paragraph.getText();
            if(text.indexOf("^m^p")!= -1 || text.indexOf("^p^m")!= -1){
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
                    //替換模板原來位置
                    run.setText("^m",0);
                }
            }
        }
    }
    
}

2.如何調(diào)用

WordUtil.convertDocxToPDF(wordFile,pdfFilePath);

3.說明
convertDocxToPDF方法中定義的fontMapper,用于存放各類字體的轉(zhuǎn)換關(guān)系俭茧,若不聲明开皿,則轉(zhuǎn)換后有可能出現(xiàn)亂碼涧黄。word中盡量使用宋體等常用字體篮昧,包括在Linux系統(tǒng)中,也需要安裝相應(yīng)的字體弓熏,才能解決亂碼問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末糠睡,一起剝皮案震驚了整個濱河市挽鞠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狈孔,老刑警劉巖信认,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異均抽,居然都是意外死亡嫁赏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門油挥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潦蝇,“玉大人,你說我怎么就攤上這事深寥∪疗梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵惋鹅,是天一觀的道長则酝。 經(jīng)常有香客問我,道長闰集,這世上最難降的妖魔是什么沽讹? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮武鲁,結(jié)果婚禮上爽雄,老公的妹妹穿的比我還像新娘。我一直安慰自己沐鼠,他們只是感情好盲链,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迟杂,像睡著了一般刽沾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上排拷,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天侧漓,我揣著相機與錄音,去河邊找鬼监氢。 笑死布蔗,一個胖子當著我的面吹牛藤违,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纵揍,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼顿乒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泽谨?” 一聲冷哼從身側(cè)響起璧榄,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吧雹,沒想到半個月后骨杂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡雄卷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年搓蚪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丁鹉。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡妒潭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出揣钦,到底是詐尸還是另有隱情杜耙,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布拂盯,位于F島的核電站佑女,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏谈竿。R本人自食惡果不足惜团驱,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望空凸。 院中可真熱鬧嚎花,春花似錦、人聲如沸呀洲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽道逗。三九已至兵罢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滓窍,已是汗流浹背卖词。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吏夯,地道東北人此蜈。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓即横,卻偏偏與公主長得像,于是被迫代替她去往敵國和親裆赵。 傳聞我的和親對象是個殘疾皇子东囚,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 2017年8月30日 星期三 晴 親子日記第十九篇 今天難得有時間接女兒放學(xué),早早來到校門口战授,想給女兒一...
    人弋三壽閱讀 189評論 0 0
  • 版權(quán)聲明:本文為LooperJing原創(chuàng)文章页藻,轉(zhuǎn)載請注明出處! 之前在Android性能優(yōu)化第(四)篇---And...
    LooperJing閱讀 5,585評論 13 49
  • 前面幾章無水君和小伙伴們分享了電腦的一些基礎(chǔ)知識爷辙,相信大家也對電腦的各個部件有一定了解。上大學(xué)交作業(yè)朦促、學(xué)習(xí)各類軟件...
    無水君閱讀 206評論 0 0
  • 文/十月云 遇到過 頑固不化的獼猴桃嗎 試試 把它和一只 千嬌百媚的香蕉 放在 一個袋子里 不出兩天 再怎么心如鋼...
    十月云閱讀 568評論 3 49
  • 一日為師务冕,終身為師血当。 非常榮幸,今年實習(xí)的時候能跟著李老師禀忆。 她高高的個子臊旭,長的馬尾辮高高梳起,給人很精神的感覺箩退。...
    愛生活的折耳貓閱讀 587評論 1 0