jacob + itext实现Word、Excel、Ppt在线预览

本文介绍了四种不同的Office在线预览技术:Office Online、OpenOffice转换、Apache POI以及Jacob。详细分析了每种方法的优点和缺点,如Office Online对域名和端口的要求,OpenOffice的样式损失,POI的兼容性问题以及Jacob的转换效率低。最终,博主作为技术新手分享了自己的实践心得。

本人技术小白一枚,前些天Boss让我写一个office在线预览的一个功能,各种找资料,总结一下我觉得比较好用的方法

网上大概有这几种office在线预览的方法

第一种

利用office online实现在线预览

Office平台提供了通过url的指向达到预览效果

http://view.officeapps.live.com/op/view.aspx?src=

后面的src填写文档上传到服务器的地址,地址需要通过用URLEncode进行编译

例: 

http://view.officeapps.live.com/op/view.aspx?src=http%3a%2f%2fvideo.ch9.ms%2fbuild%2f2011%2fslides%2fTOOL-532T_Sutter.pptx

参照链接:

https://blog.youkuaiyun.com/csdn_cjgu/article/details/69389474

优点:这个功能由Office提供所以只需要拼接地址

缺点:文档的访问地址不能直接使用 ip,需要通过域名访问,并且端口必须是 80 端口,

Word、ppt文档的大小不能超过10M,Excel不能超过5M

第二种

1.通过第三方工具openoffice,将word、excel、ppt、txt等文件转换为pdf文件,

2.通过swfTools将pdf文件转换成swf格式的文件; 

3.通过FlexPaper文档组件在页面上进行展示。 

参照链接:

https://blog.youkuaiyun.com/tmac937436/article/details/70799687?locationNum=14&fps=1

总结一下这种方法的利弊,

优点:openoffice有各种版本,支持跨平台,转换速度快;

缺点:转换的样式会有缺损,Excel和openoffice完美不兼容 =  . = ,转换的时候会出现折行,切分等情况,效果很不理想;

FlexPaper这个是用Flash插件显示的,展示的效果优点low。

第三种

利用poi实现office在线预览

  1. public static void PoiWord07ToHtml (HttpServletRequest request) throws IOException{
  2. String path= "C:\\Users\\Administrator\\Desktop\\";
  3. String file = "C:\\Users\\Administrator\\Desktop\\word07.docx";
  4. String file2 = "C:\\Users\\Administrator\\Desktop\\word07.html";
  5. File f = new File(file);
  6. if (!f.exists()) {
  7. System.out.println( "Sorry File does not Exists!");
  8. } else {
  9. if (f.getName().endsWith( ".docx") || f.getName().endsWith( ".DOCX")) {
  10. //读取文档内容
  11. InputStream in = new FileInputStream(f);
  12. XWPFDocument document = new XWPFDocument(in);
  13. File imageFolderFile = new File(path);
  14. //加载html页面时图片路径
  15. XHTMLOptions options = XHTMLOptions.create().URIResolver( new BasicURIResolver( "./"));
  16. //图片保存文件夹路径
  17. options.setExtractor( new FileImageExtractor(imageFolderFile));
  18. OutputStream out = new FileOutputStream( new File(file2));
  19. XHTMLConverter.getInstance().convert(document, out, options);
  20. out.close();
  21. } else {
  22. System.out.println( "Enter only MS Office 2007+ files");
  23. }
  24. }
  25. }

总结一下这种方法的利弊

优点:纯java代码不需要第三方软件,poi对于Excel的解析比较好,可以完美转换

缺点:jar包真的好难找啊,各种版本不兼容问题,比如word03和word07生成的分别是.doc和docx,poi对于.doc不识别,然后各种报错,由于生成的是Html所以它会把Word中的图片单独存放在一个文件下很占空间。

第四种

使用jacob实现office转换pdf达到预览功能

pom文件中引用

<dependency>
  <groupId>net.sf.jacob-project</groupId>
  <artifactId>jacob</artifactId>
  <version>1.14.3</version>
</dependency>

<dependency>
  <groupId>com.lowagie</groupId>
  <artifactId>itext</artifactId>
  <version>2.1.7</version>
</dependency>
<!--poi-->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>3.14-beta1</version>

</dependency>

网上查找jacob对应版本包把jacob-1.14.3-x64.dll复制到需要在Java\jdk1.8.0\jre\bin目录下,

经过多次测试发现jacob对于Excel的转换有些问题,所以Excel的转换我用的是poi

自定义一个工具类Word2Pdf

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import java.io.*;

public class Word2Pdf {
    static final int wdDoNotSaveChanges = 0;// 不保存待定的更改。
    static final int wdFormatPDF = 17;// word转PDF 格式
    static final int ppSaveAsPDF = 32;// ppt 转PDF 格式

    public static void main(String[] args) throws IOException {
        
    }

    public void word2pdf(String wordPath,String target,String wordName,String suffix){

        System.out.println("启动Word");
        long start = System.currentTimeMillis();
        String source = wordPath + wordName + suffix;
        target = target + wordName ;
        ActiveXComponent app = null;
        try {
            app = new ActiveXComponent("Word.Application");
            app.setProperty("Visible", false);
            app.setProperty("DisplayAlerts", new Variant(false));
            Dispatch docs = app.getProperty("Documents").toDispatch();
            System.out.println("打开文档" + source);
            Dispatch doc = Dispatch.call(docs,//
                    "Open", //
                    source,// FileName
                    false,// ConfirmConversions
                    true // ReadOnly
            ).toDispatch();
            System.out.println("转换文档到PDF " + target);
            File tofile = new File(target);
            //验证目标路径是否存在
            if (tofile.exists()) {
                System.out.println("存在");
            }
            Dispatch.call(doc,//
                    "SaveAs", //
                    target, // FileName
                    wdFormatPDF);

            Dispatch.call(doc, "Close", false);
            long end = System.currentTimeMillis();
            System.out.println("转换完成..用时:" + (end - start) + "ms.");
//            Cut.cutfile(str_s,str_d);
        } catch (Exception e) {
            System.out.println("========Error:文档转换失败:" + e.getMessage());
        } finally {
            if (app != null)
                app.invoke("Quit", wdDoNotSaveChanges);
        }
    }

    public void ppt2pdf(String wordPath,String target,String wordName,String suffix){
        System.out.println("启动PPT");
        String source = wordPath + wordName + suffix;
        target = target + wordName ;
        long start = System.currentTimeMillis();
        ActiveXComponent app = null;
        try {
            app = new ActiveXComponent("Powerpoint.Application");
            Dispatch presentations = app.getProperty("Presentations").toDispatch();
            System.out.println("打开文档" + source);
            Dispatch presentation = Dispatch.call(presentations,//
                    "Open",
                    source,// FileName
                    true,// ReadOnly
                    true,// Untitled 指定文件是否有标题。
                    false // WithWindow 指定文件是否可见。
            ).toDispatch();

            System.out.println("转换文档到PDF " + target);
            File tofile = new File(target);
            if (tofile.exists()) {
                tofile.delete();
            }
            Dispatch.call(presentation,//
                    "SaveAs", //
                    target, // FileName
                    ppSaveAsPDF);

            Dispatch.call(presentation, "Close");
            long end = System.currentTimeMillis();
            System.out.println("转换完成..用时:" + (end - start) + "ms.");

        } catch (Exception e) {
            System.out.println("========Error:文档转换失败:" + e.getMessage());
        } finally {
            if (app != null) app.invoke("Quit");
        }
    }
}

再定义一个poi转换Html的一个类ExcelToHtml

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class ExcelToHtml {
    private final static ExcelToHtml oOfficeToXML = new ExcelToHtml();

    public static ExcelToHtml getInstance() {
        return oOfficeToXML;
    }

    public ExcelToHtml() {
    }

    /**
     * 因为poi转换的Html页面在浏览器中显示时会出现乱码问题,这里强制转换一下
     * @param filePath
     */
    public void html2utf(String filePath) {
        try {
            String content = "charset=utf-8";
            String templateContent = "";
            FileInputStream fileinputstream = new FileInputStream(filePath);// 读取模板文件
            // 下面四行:获得输入流的长度,然后建一个该长度的数组,然后把输入流中的数据以字节的形式读入到数组中,然后关闭流
            int lenght = fileinputstream.available();
            byte bytes[] = new byte[lenght];
            fileinputstream.read(bytes);
            fileinputstream.close();
            // 通过使用默认字符集解码指定的 byte 数组,构造一个新的
            //因为原来的html文件是gb2312格式,所以转为string时也要以GBK格式读取,不然依旧是乱码
            templateContent = new String(bytes, "GBK");
            templateContent = templateContent.replaceFirst("charset=gb2312", content);
            // 因为已经替换字符串了,所以使用UTF-8字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
            byte tag_bytes[] = templateContent.getBytes("UTF-8");
            FileOutputStream fileoutputstream = new FileOutputStream(filePath);// 建立文件输出流
            fileoutputstream.write(tag_bytes);
            fileoutputstream.close();
        } catch (Exception e) {
            System.out.print(e.toString());
        }
    }

    public boolean ExceltoHtml(String wordPath,String original_name,String target,String wordName,String suffix) {
        ComThread.InitSTA();
        ActiveXComponent activexcomponent = new
                ActiveXComponent("Excel.Application");
        String source = wordPath + original_name + suffix;
        target = target + wordName;
        boolean flag = false;
        try
        {
            activexcomponent.setProperty("Visible", new Variant(false));
            Dispatch dispatch =
                    activexcomponent.getProperty("Workbooks").toDispatch();
            Dispatch dispatch1 = Dispatch.invoke(dispatch, "Open", 1, new
                    Object[] {
                    source, new Variant(false), new Variant(true)
            }, new int[1]).toDispatch();
            Dispatch.call(dispatch1, "SaveAs", target, new Variant(44));
            Variant variant = new Variant(false);
            Dispatch.call(dispatch1, "Close", variant);
            flag = true;
        }
        catch(Exception exception)
        {
            System.out.println("|||" + exception.toString());
        }
        finally
        {
            activexcomponent.invoke("Quit", new Variant[0]);
            ComThread.Release();
            ComThread.quitMainSTA();
        }
        return flag;
    }

}

主要的两个类已完成,因为这只是一个小demo所以代码可能有些不太规范

controller类

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import pojo.UpFile;
import tools.ExcelToHtml;
import tools.Word2Pdf;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/sys")
public class controller {
    
    Word2Pdf word2Pdf = new Word2Pdf();

    @RequestMapping("/index")
    public ModelAndView index(){
        ModelAndView modelAndView = new ModelAndView();
//        Word2Pdf word2Pdf = new Word2Pdf();
//        word2Pdf.word2pdf("G:\\Test\\","G:\\Test\\PDF\\","",".doc");
//        modelAndView.setViewName("index");
        return modelAndView;
    }


    @RequestMapping(value="/upload.json",method=RequestMethod.POST)
    @ResponseBody
    public Map<Object,Object> upload(@RequestParam("file") MultipartFile file, HttpServletRequest request)  throws Exception  {
        UpFile upFile = new UpFile();
        Map<Object,Object> map = new HashMap<Object, Object>();
        String suffix = file.getOriginalFilename().substring(
                file.getOriginalFilename().lastIndexOf("."));
        String fileName = file.getOriginalFilename().substring(0,
                file.getOriginalFilename().lastIndexOf("."));
        String time = new SimpleDateFormat("yyyyMMddHHmmssSSS") .format(new Date() );
        String filePath = request.getSession().getServletContext().getRealPath("upload/");
        String target = "G:\\Test_02\\target\\backend\\statics\\pdf\\";
//        String FileName = "\\statics\\pdf\\"+fileName+".pdf";
        String FileName = "/statics/pdf/"+fileName+".pdf";
//        上传到/target/backend/upload/的暂存文件夹下
        File dir = new File(filePath,fileName+suffix);
        file.transferTo(dir);
        if (suffix.equals(".doc")||suffix.equals(".docx")){
            WordToPdf(filePath,target,fileName,suffix);
        } else if (suffix.equals(".ppt")||suffix.equals(".pptx")){
            PptToPdf(filePath,target,fileName,suffix);
        } else if (suffix.equals(".xls")||suffix.equals(".xlsx")) {
            //有些浏览器会把html名字中的中文进行编译,导致404 所以我名字我就用时间戳代替了
            //原文件名
            String original_name = fileName;
            //更改后的名字
            String changeName = "Html" + time;
            ExcelToHtml(filePath, original_name, changeName, suffix);
            FileName = "\\statics\\Html\\" + changeName + ".htm";
        }
        map.put("filename",FileName);
        return map;
    }

    public void WordToPdf(String filePath,String target,String fileName,String suffix){
        word2Pdf.word2pdf(filePath,target,fileName,suffix);
    }

    public void PptToPdf(String filePath,String target,String wordName,String suffix){
        word2Pdf.ppt2pdf(filePath,target,wordName,suffix);
    }


    public void ExcelToHtml(String filePath,String original_name,String wordName,String suffix){
        ExcelToHtml excelToHtml = new ExcelToHtml();
        excelToHtml.ExceltoHtml(filePath,original_name,"G:\\Test_02\\target\\backend\\statics\\Html\\",wordName,suffix);
        excelToHtml.html2utf("G:\\Test_02\\target\\backend\\statics\\Html\\"+wordName+".htm");
    }
}

前台页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="/statics/jquery-3.2.1.min.js"></script>
    <script type="text/javascript">
        var filePath = "";

        function load(){
            if (filePath==""||filePath.length==0){
                alert("请先上传文件");
            }
            document.getElementById("iframe").src=filePath
        }

        function test(){
            var form = new FormData(document.getElementById("form"));
            $.ajax({
                url:"/sys/upload.json",
                type:"post",
                data:form,
                cache: false,
                processData: false,
                contentType: false,
                success:function(data){
                    filePath = (data.filename);
                    alert("上传成功");
                }, error:function(e){
                    alert(e.error);
                    window.clearInterval(timer);
                }
            })
        }
    </script>
</head>
<body>
<form class="form" enctype="multipart/form-data" id="form">
    选择文件:<input type="file" name="file" width="180px">
    <input type="button" value="上传" onclick="test()">
    <input type="button" value="预览" onclick="load()">
</form>
<iframe src="" id="iframe" width="100%" height="650px"/>
</body>
</html>

总结一下jacob的利弊

优点:相对于其他方法可以较为完好的转换

缺点:转换效率很低,通常一个Word需要4s左右,大一点的文件就很慢了,不支持跨平台,只能在windows下运行。


由于博主作为一个小菜鸟第一次博客一些不足和缺失请多多担待




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值