采用jacob實現word轉pdf


網絡上已經有很多這方面的內容,在用之前也是參考了好多別人的文章,下面記錄下我自己的整合過程。整個過程都比較簡單:

開發環境:win8 64位系統,在2008下面部署也是一樣的。

文檔要求jdk的版本要1.7的某個版本以上,我用的是:java version "1.7.0_80"

其他系統和環境可以下載相應的舊版本。

我是從http://sourceforge.net/projects/jacob-project/files/jacob-project/ 這里下載最新的版本jacob-1.18-M2

一個簡單的工具類:

package cn.xm.exam.utils;

import java.io.File;
import java.io.IOException;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;

/**
 * word轉pdf的工具
 * 
 * @author QiaoLiQiang
 * @time 2018年1月4日下午2:18:33
 */
public class Word2PdfUtil {

    static final int wdDoNotSaveChanges = 0;// 不保存待定的更改。
    static final int wdFormatPDF = 17;// word轉PDF 格式

    public static void main(String[] args) throws IOException {
        String source1 = "C:\\Users\\liqiang\\Desktop\\考試試卷.doc";
        String target1 = "C:\\Users\\liqiang\\Desktop\\考試試卷.pdf";
        Word2PdfUtil.word2pdf(source1, target1);
    }

    /**
     * 
     * @param source
     *            word路徑
     * @param target
     *            生成的pdf路徑
     * @return
     */
    public static boolean word2pdf(String source, String target) {
        System.out.println("Word轉PDF開始啟動...");
        long start = System.currentTimeMillis();
        ActiveXComponent app = null;
        try {
            app = new ActiveXComponent("Word.Application");
            app.setProperty("Visible", false);
            Dispatch docs = app.getProperty("Documents").toDispatch();
            System.out.println("打開文檔:" + source);
            Dispatch doc = Dispatch.call(docs, "Open", source, false, true).toDispatch();
            System.out.println("轉換文檔到PDF:" + target);
            File tofile = new File(target);
            if (tofile.exists()) {
                tofile.delete();
            }
            Dispatch.call(doc, "SaveAs", target, wdFormatPDF);
            Dispatch.call(doc, "Close", false);
            long end = System.currentTimeMillis();
            System.out.println("轉換完成,用時:" + (end - start) + "ms");
            return true;
        } catch (Exception e) {
            System.out.println("Word轉PDF出錯:" + e.getMessage());
            return false;
        } finally {
            if (app != null) {
                app.invoke("Quit", wdDoNotSaveChanges);
            }
        }
    }

}

 

 

 

結果:

Word轉PDF開始啟動...
打開文檔:C:\Users\liqiang\Desktop\考試試卷.doc
轉換文檔到PDF:C:\Users\liqiang\Desktop\考試試卷.pdf
轉換完成,用時:8606ms

 

 

 

整個代碼只需要一個jacob的jar包就可以運行了。
當然,在下載的文件里面還有個調用系統庫的dll文件需要放置在jre的bin目錄下:
示例:D:\Java\jdk1.7.0_67\jre\bin\jacob-1.18-M2-x64.dll
這樣代碼就可以實現word轉pdf了。

 

下面附上maven的pom.xml配置,因為jacob包沒在第三方倉庫上面直接找到,所以需要手動上傳到maven中央庫,或者配置下本地路徑,下面粘下本地路徑的配置:

<dependency>  
            <groupId>com.jacob</groupId>  
            <artifactId>jacob</artifactId>  
            <version>1.18-M2</version>  
            <scope>system</scope>  
            <systemPath>C:/Users/Downloads/jacob-1.18-M2/jacob.jar</systemPath>  
        </dependency>  

這樣項目構建的時候就不會出錯。
順便提一句:在部署的服務器上面需要安裝office軟件,要不然轉換不成功,會報錯。

查看office激活剩余天數方法參考:

https://zhidao.baidu.com/question/1047689643813754659.html

 

 

 

在windowsServer2012服務器上安裝office之后報錯:VariantChangeType failed

解決辦法:

Windows Vista/2012改變了COM對象默認的交互方式為“非交互”型的。Console啟動本身支持應用交互,但service模式下就不行了。所以需要修改word DCOM默認的標識,改為“交互式用戶”模式,即可正常調用了。

按照以下步驟修改后再測service模式下試轉Word即可成功: 
1) 運行命令: mmc comexp.msc -32 
2) 找到:組件服務>計算機>我的電腦>DCOM組件>Microsoft Word 97-2003 文檔; 
3) 右鍵點擊,選擇屬性,修改標識為“交互式用戶”,點擊“確定”;

 

 放在服務器上也報一個錯誤:com.jacob.com.ComFailException: Can't co-create object解決辦法

 解決辦法:

在使用jacob調用VB.NET寫的dll時,總是報錯 
com.jacob.com.ComFailException: Can't co-create object 
at com.jacob.com.Dispatch.createInstanceNative(Native Method) 
at com.jacob.com.Dispatch.<init>(Dispatch.java:99) 
at com.jacob.samples.test.CallDll.JavaCallVbdll(CallDll.java:19) 
at com.jacob.samples.test.CallDll.main(CallDll.java:13) 

網上找到幾種解決辦法: 
1.沒有釋放com線程或者干脆沒有使用com線程控制。因此解決方案即:釋放com線程(ComThread.Release();)。因此修改代碼為 
public static String JavaCallVbdll(String str){ 
ComThread.InitSTA(); 
String res=""; 
try { 
Dispatch test = new Dispatch("TestDLL.ComClass1"); 
Variant result = Dispatch.call(test, "teststr", str); 
res=result.toString(); 
}catch (Exception e) { 
res=""; 
e.printStackTrace(); 
}finally { 
ComThread.Release(); 
} 
return res; 
} 

對不起,不成功!!!! 
2.在系統的服務進程中,找到“DCom Server Process Launcher”這個服務選項,請確認這個服務是關閉着的,還是開啟的。 
http://babystudyjava.iteye.com/blog/1746597 
不好意思,我們開着呢!!! 
3.JDK與JACOB版本對應,我的JDK是1.7,JACOB是1.17,電腦是win10,都是64位的。 
奔潰,各版本都試過!!! 
4.jar和dll文件版本需對應,jar包是64位的,dll文件是同事開發的,所以就去詢問同事給我的是什么版本的dll,同事當時不造。。。

后來在Google找到一篇帖子說在VB.NET中編譯選擇的平台如果是Any CPU,那么久意味着生成的dll文件是32位的。沒想到我們的dll文件真的是這樣編譯的!這里寫圖片描述 
如上圖:將Any CPU換成x64重新編譯就可以了。

如此問題就解決了!!!

 

 

最后還是不穩定,最終決定直接生成pdf文件:參考http://www.cnblogs.com/qlqwjy/p/8213989.html 

 

 

 

 

附一個freemarker模板生成doc文檔之后轉為pdf的代碼:

package cn.xm.exam.action.exam.exam;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;

import cn.xm.exam.bean.exam.Exampaper;
import cn.xm.exam.service.exam.examPaper.ExamPaperService;
import cn.xm.exam.utils.RemoveHtmlTag;
import cn.xm.exam.utils.Word2PdfUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import jxl.common.Logger;

/**
 * 導出試卷 1.查出數據 2.Word 3.打開流,提供下載
 * 
 * @author QiaoLiQiang
 * @time 2017年10月31日下午10:29:51
 */
@Controller
@Scope("prototype")
@SuppressWarnings("all")
public class ExtExamPaperAction extends ActionSupport {
    private Logger logger = Logger.getLogger(FindExamAction.class);
    private String fileName;// 導出的Excel名稱
    @Autowired
    private ExamPaperService examPaperService;
    // 1.查數據
    private String paperId;

    public Exampaper findPaperAllInfoById() {
        Exampaper paper = null;
        try {
            paper = RemoveHtmlTag.removePaperTag(examPaperService.getPaperAllInfoByPaperId(paperId));
        } catch (SQLException e) {
            logger.error("查詢試卷所有信息出錯!!!", e);
        }
        return paper;
    }

    // 2.寫入Word
    public void writeExamPaper2Word(Exampaper paper) {
        // 獲取路徑
        String path = ServletActionContext.getServletContext().getRealPath("/files/papers");
        // 用於攜帶數據的map
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("paper", paper);
        String filePath = path + "\\" + fileName + ".doc";
        // Configuration用於讀取ftl文件
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        // 指定路徑的第一種方式(根據某個類的相對路徑指定)
        configuration.setClassForTemplateLoading(this.getClass(), "");
        // 輸出文檔路徑及名稱
        File outFile = new File(filePath);
        // 獲取文件的父文件夾並刪除文件夾下面的文件
        File parentFile = outFile.getParentFile();
        // 獲取父文件夾下面的所有文件
        File[] listFiles = parentFile.listFiles();
        if (parentFile != null && parentFile.isDirectory()) {
            for (File fi : listFiles) {
                // 刪除文件
                fi.delete();
            }
        }
        // 以utf-8的編碼讀取ftl文件
        try {
            Template t = configuration.getTemplate("paperModel.ftl", "utf-8");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
            t.process(dataMap, out);
            out.close();
        } catch (Exception e) {
            logger.error("寫入word出錯!", e);
        }
    }

    // 3.打開文件的流提供下載
    public InputStream getInputStream() throws Exception {
        Exampaper paper = this.findPaperAllInfoById();// 查數據
        this.writeExamPaper2Word(paper);// 寫入數據
        String path = ServletActionContext.getServletContext().getRealPath("/files/papers");
        String filepath = path + "\\" + fileName + ".doc";
        String destPath = path + "\\" + fileName + ".pdf";
        Word2PdfUtil.word2pdf(filepath, destPath);
        File file = new File(destPath);
        // 只用返回一個輸入流
        return FileUtils.openInputStream(file);// 打開文件
    }

    // 文件下載名
    public String getDownloadFileName() {
        String downloadFileName = "";
        String filename = fileName + ".pdf";
        try {
            downloadFileName = new String(filename.getBytes(), "ISO8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return downloadFileName;
    }

    @Override
    public String execute() throws Exception {
        // 先將名字設為秒數產生唯一的名字
        // this.setFileName(String.valueOf(System.currentTimeMillis()));
        this.setFileName("考試試卷");
        return super.execute();
    }

    // get,set方法
    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getPaperId() {
        return paperId;
    }

    public void setPaperId(String paperId) {
        this.paperId = paperId;
    }

}

 

 

 

 

 

 

其他一些參數和word,ppt,excel,jpg轉pdf轉換請參考其他兩個鏈接:

http://hu437.iteye.com/blog/844350
http://blog.csdn.net/xuchaozheng/article/details/19199721

更全的:http://blog.csdn.net/catoop/article/details/43150671

 

其他的轉換方法參考:

http://feifei.im/archives/93

 

一個word轉html的工具類:

package cn.xm.exam.utils;

import java.io.File;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

/**
 * 實現word轉換為HTML
 * 
 * @author QiaoLiQiang
 * @time 2018年2月3日下午2:17:43
 */
public class Word2HtmlUtil {

    // 8 代表word保存成html
    public static final int WORD_HTML = 8;

    public static void main(String[] args) {
        String docfile = "C:\\Users\\liqiang\\Desktop\\sbgl.docx";
        String htmlfile = "C:\\Users\\liqiang\\Desktop\\sbgl.html";
        Word2HtmlUtil.wordToHtml(docfile, htmlfile);
    }

    /**
     * WORD轉HTML
     * 
     * @param docfile
     *            WORD文件全路徑
     * @param htmlfile
     *            轉換后HTML存放路徑
     */
    public static boolean wordToHtml(String inPath, String toPath) {

        // 啟動word
        ActiveXComponent axc = new ActiveXComponent("Word.Application");

        boolean flag = false;

        try {
            // 設置word不可見
            axc.setProperty("Visible", new Variant(false));

            Dispatch docs = axc.getProperty("Documents").toDispatch();

            // 打開word文檔
            Dispatch doc = Dispatch.invoke(docs, "Open", Dispatch.Method,
                    new Object[] { inPath, new Variant(false), new Variant(true) }, new int[1]).toDispatch();

            // 作為html格式保存到臨時文件
            Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] { toPath, new Variant(8) }, new int[1]);

            Variant f = new Variant(false);
            Dispatch.call(doc, "Close", f);
            flag = true;
            return flag;

        } catch (Exception e) {
            e.printStackTrace();
            return flag;
        } finally {
            axc.invoke("Quit", new Variant[] {});
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM