zoukankan      html  css  js  c++  java
  • 采用jacob实现word转pdf luoye

    转自:https://www.cnblogs.com/qlqwjy/p/8193281.html

    开发环境: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[] {});
            }
        }
    }
  • 相关阅读:
    DRUPAL-PSA-CORE-2014-005 && CVE-2014-3704 Drupal 7.31 SQL Injection Vulnerability /includes/database/database.inc Analysis
    WDCP(WDlinux Control Panel) mysql/add_user.php、mysql/add_db.php Authentication Loss
    Penetration Testing、Security Testing、Automation Testing
    Tomcat Server Configuration Automation Reinforcement
    Xcon2014 && Geekpwn2014
    phpMyadmin /scripts/setup.php Remote Code Injection && Execution CVE-2009-1151
    Linux System Log Collection、Log Integration、Log Analysis System Building Learning
    The Linux Process Principle,NameSpace, PID、TID、PGID、PPID、SID、TID、TTY
    Windows Management Instrumentation WMI Security Technology Learning
    IIS FTP Server Anonymous Writeable Reinforcement, WEBDAV Anonymous Writeable Reinforcement(undone)
  • 原文地址:https://www.cnblogs.com/luoyetl/p/9566799.html
Copyright © 2011-2022 走看看