Java中如何实现文件预览的功能

2年前 (2022) 程序员胖胖胖虎阿
345 0 0

文件预览方法总结

  • 前言
  • 一、kkfileview 文件在线预览
  • 二、officetohtml纯前端的方式
  • 三、JODConverter
  • 四、Aspose
  • 总结

前言

日常开发中常见的文件格式有pdf,word,Excel,PPT,Html,txt,图片等。pdf,Html,txt,图片这种实现在线预览非常简单,有一些前端的插件可以满足要求。word,Excel,PPT如果要实现在线预览,就非常的困难。word,Excel,PPT实现在线预览常用的方式就是先转换成pdf,然后在进行预览。下面我就介绍常用的几种方案

一、kkfileview 文件在线预览

此项目为文件文档在线预览项目解决方案,项目使用流行的 spring boot 搭建,易上手和部署,部署好后可以独立提供预览服务,使用 http 接口访问,不需要和应用集成,具有跨系统跨语言使用的特性。提供 zip/tar.gz 发行包、自定义配置文件、和启动 / 停止脚本等,极大方便部署使用,同时官方发布 Docker 镜像,方便容器环境中部署使用。基本支持主流办公文档的在线预览,如 doc,docx,dwg, ofd, xls,xlsx,ppt,pptx,pdf,txt,zip,rar,7z,mp3,mp4,flv 图片等等。
项目地址:https://gitee.com/kekingcn/file-online-preview
项目官网:https://kkfileview.keking.cn

二、officetohtml纯前端的方式

用纯 javascript 编写的 jQuery 插件,用于将现代 Microsoft Office 文件、pptx、docx、xlsx 和 pdf 转换为 html。
实际上它是一个应用程序,它集成了其他库,如PPTXjs, mammoth.js,SheetJs结合 handsontable 和PDF.js,旨在将 Office 文件和 pdf 文件转换为 HTML。
项目官网:https://officetohtml.js.org/index.html

三、JODConverter

JODConverter是一种Java OpenDocument转换器,能够转换不同格式的文档,它依赖于Apache OpenOffice或 LibreOffice ,它为OpenDocument和Microsoft Office提供了最好的免费导入/导出的过滤器。
JODConverter可以用在这几种地方:
作为一个Java类库,嵌入到你的Java应用程序中。
作为一个命令行工具,可以在你的脚本中调用。
作为一个简单的web应用,上传文档,选择转换的格式并下载转换后的版本。
可以用openoffice,实现原理就是:
通过第三方工具openoffice,将word、excel、ppt、txt等文件转换为pdf文件流;这样就可以在浏览器上实现预览了。
先去openoffice官网下载进行安装,官网地址:https://www.openoffice.org/download/ 安装完成后启动。
Java中如何实现文件预览的功能

java中的代码如下:
Maven中添加如下依赖

    <dependency>
        <groupId>com.artofsolving</groupId>
        <artifactId>jodconverter</artifactId>
        <version>2.2.1</version>
    </dependency>

将word、excel、ppt转换为pdf流的工具类代码

  import com.artofsolving.jodconverter.DefaultDocumentFormatRegistry;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.DocumentFormat;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
 
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
 
 
/**
 * 文件格式转换工具类
 *
 * @version 1.0
 * @since JDK1.8
 */
public class FileConvertUtil {
    /** 默认转换后文件后缀 */
    private static final String DEFAULT_SUFFIX = "pdf";
    /** openoffice_port */
    private static final Integer OPENOFFICE_PORT = 8100;
 
    /**
     * 方法描述 office文档转换为PDF(处理本地文件)
     *
     * @param sourcePath 源文件路径
     * @param suffix     源文件后缀
     * @return InputStream 转换后文件输入流
     * @author tarzan
     */
    public static InputStream convertLocaleFile(String sourcePath, String suffix) throws Exception {
        File inputFile = new File(sourcePath);
        InputStream inputStream = new FileInputStream(inputFile);
        return covertCommonByStream(inputStream, suffix);
    }
 
    /**
     * 方法描述  office文档转换为PDF(处理网络文件)
     *
     * @param netFileUrl 网络文件路径
     * @param suffix     文件后缀
     * @return InputStream 转换后文件输入流
     * @author tarzan
     */
    public static InputStream convertNetFile(String netFileUrl, String suffix) throws Exception {
        // 创建URL
        URL url = new URL(netFileUrl);
        // 试图连接并取得返回状态码
        URLConnection urlconn = url.openConnection();
        urlconn.connect();
        HttpURLConnection httpconn = (HttpURLConnection) urlconn;
        int httpResult = httpconn.getResponseCode();
        if (httpResult == HttpURLConnection.HTTP_OK) {
            InputStream inputStream = urlconn.getInputStream();
            return covertCommonByStream(inputStream, suffix);
        }
        return null;
    }
 
    /**
     * 方法描述  将文件以流的形式转换
     *
     * @param inputStream 源文件输入流
     * @param suffix      源文件后缀
     * @return InputStream 转换后文件输入流
     * @author tarzan
     */
    public static InputStream covertCommonByStream(InputStream inputStream, String suffix) throws Exception {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        OpenOfficeConnection connection = new SocketOpenOfficeConnection(OPENOFFICE_PORT);
        connection.connect();
        DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
        DefaultDocumentFormatRegistry formatReg = new DefaultDocumentFormatRegistry();
        DocumentFormat targetFormat = formatReg.getFormatByFileExtension(DEFAULT_SUFFIX);
        DocumentFormat sourceFormat = formatReg.getFormatByFileExtension(suffix);
        converter.convert(inputStream, sourceFormat, out, targetFormat);
        connection.disconnect();
        return outputStreamConvertInputStream(out);
    }
 
    /**
     * 方法描述 outputStream转inputStream
     *
     * @author tarzan
     */
    public static ByteArrayInputStream outputStreamConvertInputStream(final OutputStream out) throws Exception {
        ByteArrayOutputStream baos=(ByteArrayOutputStream) out;
        return new ByteArrayInputStream(baos.toByteArray());
    }
 
 
 
    public static void main(String[] args) throws IOException {
        //convertNetFile("http://172.16.10.21/files/home/upload/department/base/201912090541573c6abdf2394d4ae3b7049dcee456d4f7.doc", ".pdf");
        //convert("c:/Users/admin/Desktop/2.pdf", "c:/Users/admin/Desktop/3.pdf");
    }
}

serve层在线预览方法代码

 /**
     * @Description:系统文件在线预览接口
     */
    public void onlinePreview(String url, HttpServletResponse response) throws Exception {
        //获取文件类型
        String[] str = SmartStringUtil.split(url,"\\.");
 
        if(str.length==0){
            throw new Exception("文件格式不正确");
        }
        String suffix = str[str.length-1];
        if(!suffix.equals("txt") && !suffix.equals("doc") && !suffix.equals("docx") && !suffix.equals("xls")
                && !suffix.equals("xlsx") && !suffix.equals("ppt") && !suffix.equals("pptx")){
            throw new Exception("文件格式不支持预览");
        }
        InputStream in=FileConvertUtil.convertNetFile(url,suffix);
        OutputStream outputStream = response.getOutputStream();
        //创建存放文件内容的数组
        byte[] buff =new byte[1024];
        //所读取的内容使用n来接收
        int n;
        //当没有读取完时,继续读取,循环
        while((n=in.read(buff))!=-1){
            //将字节数组的数据全部写入到输出流中
            outputStream.write(buff,0,n);
        }
        //强制将缓存区的数据进行输出
        outputStream.flush();
        //关流
        outputStream.close();
        in.close();
    }

四、Aspose

Aspose.Words是一款先进的类库,通过它可以直接在各个应用程序中执行各种文档处理任务。Aspose.Words支持DOC,OOXML,RTF,HTML,OpenDocument, PDF, XPS, EPUB和其他格式。使用Aspose.Words,可以生成,更改,转换,渲染和打印文档而不使用Microsoft Word。
实现原理也是通过Aspose把文件转换成pdf然后在预览,实现步骤如下:
添加jar包,下载地址:https://download.csdn.net/download/xinghui_liu/85931977
配置License.xml,去掉水印

<?xml version="1.0" encoding="UTF-8" ?>
<License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Words for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
    </Data>
    <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>

添加如下工具类,程序中调用doc2pdf即可实现文件转pdf

package com.weemambo.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;

public class Word2PdfAsposeUtil {


    public static boolean getLicense() {
        boolean result = false;
        InputStream is = null;
        try {
            Resource resource = new ClassPathResource("license.xml");
            is = resource.getInputStream();
            //InputStream is = Word2PdfAsposeUtil.class.getClassLoader().getResourceAsStream("license.xml"); // license.xml应放在..\WebRoot\WEB-INF\classes路径下
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    public static boolean doc2pdf(String inPath, String outPath) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return false;
        }
        FileOutputStream os = null;
        try {
            long old = System.currentTimeMillis();
            File file = new File(outPath); // 新建一个空白pdf文档
            os = new FileOutputStream(file);
            Document doc = new Document(inPath); // Address是将要被转化的word文档
            doc.save(os, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
            // EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            System.out.println("pdf转换成功,共耗时:" + ((now - old) / 1000.0) + "秒"); // 转化用时
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }finally {
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }
}

如上代码在window下不会出现乱码,在Linux系统中会出现乱码,原因为Linux系统中缺少相应的字体。解决方案如下:
获取window字体C:\Windows\Fonts目录下字体复制到 Linux /usr/share/fonts/win,具体步骤如下:
1.把字体上传到ninux服务器。这里上传到 /home 目录。
2.把刚刚上传的字体解压:unzip Fonts.zip -d Fonts
3.创建字体目录:mkdir /usr/share/fonts/win
4.把解压后的字体复制到创建的字体目录中:cp /home/Fonts/Fonts/* /usr/share/fonts/win
5.安装字体:

cd /usr/share/fonts
sudo mkfontscale
sudo mkfontdir 
sudo fc-cache -fv

6.执行命令让字体生效

source /etc/profile

7.如果安装失败,可以考虑修改字体权限

chmod 755 *.ttf

8.重启服务器就可以正常转换了

总结

上面介绍了四种文件预览的方法,每种方法的优缺点如下:
方法一:kkfileview支持文件格式多,而且不用开发。不过需要单独部署一个文件预览的服务,而且服务器也需要安装openoffice。
方法二:officetohtml纯前端的方式可以不用安装任何插件及服务,但是目前只支持文件地址的方式预览,如果是文件流的话无法使用
方法三:JODConverter 依赖于openoffice,需要在服务器单独安装openoffice。
方法四:Aspose使用的是破解版的,如果商用使用需要考虑版权问题。

综上所述,如果不能在服务器安装相应的软件,而且程序中的附件是以地址的方式访问的话使用officetohtml。如果服务器可以安装插件,优先kkfileview,Aspose,JODConverter 。

三,四都是将文件转换成pdf,前端可以使用pdfjs,官网地址为:http://mozilla.github.io/pdf.js/getting_started/#download
下载完成后放入到项目中,如下:
Java中如何实现文件预览的功能
在项目中新建一个viewPdf.jsp页面:

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>	
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<title>文件预览</title>
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link rel="stylesheet" type="text/css" href="<%=request.getContextPath()%>/resources/layui/css/layui.css">
<script type="text/javascript" src="<%=request.getContextPath()%>/resources/layui/layui.js?v=1.1"></script>
<script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-1.8.3.js"></script>
    <script type="text/javascript">
        $(function() {
            $("#pdf").attr("height", $(document).height());
            var fileId='${fileId}';
            var url = "${pageContext.request.contextPath}/pdfjs/web/viewer.html?file=${pageContext.request.contextPath}/xxxx.do?fileId="+fileId;
            $("#pdf").attr("src", url);
        })
    </script>
</head>
<body>
<div class="main">
    <iframe id="pdf" width="100%"></iframe>
</div>
</body>
</html>

file后面可以直接写一个文件地址,如果是文件流的方式写一个后端的请求并传递相应的参差。文件流要注意的地方是下面这个要设置为inline
response.setHeader(“Content-disposition”, “inline; filename=” + fileName);

参考:
https://blog.csdn.net/weixin_40986713/article/details/109527294

https://blog.csdn.net/qq_20143059/article/details/106427297

https://blog.csdn.net/wybaby168/article/details/122842866

版权声明:程序员胖胖胖虎阿 发表于 2022年9月14日 上午10:08。
转载请注明:Java中如何实现文件预览的功能 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...