springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能

 

应用场景及实现思路

应用场景:给定一个网址,输入网址后立即显示预览文件。

实现思路:
1、将文件下载到本地,存储到某个指定目录 
2、进行文件转换,此处是重点     
3、进行文件展示

实现过程

首先,搭建一个springboot项目,搭建完毕后项目结构如图:

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第1张图片

目录结构中static存放的是静态资源,templates中存放页面。其中配置文件里存放我们的配置信息:application.yml

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第2张图片

其中tmp:root下面是转换后文件的存放位置,rootTemp则是下载文件的临时存放位置,后续会有定时器定时删除该目录下的内容,soffice:home配置的是openoffice的安装目录,因为office文件的转换要用到openoffice。其中的type则是可以预览的文件类型。好了,搭建完毕之后开始搭建Service层,Dao层(可用可不用),Controller层。整体搭建完毕之后如下图:

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第3张图片

相关依赖pom.xml



	4.0.0

	file-conventer
	Demo project for Spring Boot

	
		org.springframework.boot
		spring-boot-starter-parent
		1.5.9.RELEASE
		 
	

	
		UTF-8
		UTF-8
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		
			net.sourceforge.jchardet
			jchardet
			1.0
		
		
		
			org.artofsolving.jodconverter
			jodconverter-core
			3.0.0
		
        
            org.apache.commons
            commons-compress
            1.11
        
		
		
			org.apache.commons
			commons-compress
			1.9
		
		
		
			com.github.junrar
			junrar
			0.7
		
		
			com.google.guava
			guava
			19.0
		
		
			commons-codec
			commons-codec
			2.0-SNAPSHOT
		
		
		
			net.lingala.zip4j
			zip4j
			1.3.2
		
        
            org.springframework
            spring-context-support
            4.3.10.RELEASE
        
		
			org.freemarker
			freemarker
			2.3.25-incubating
		
		
		
			net.sf.json-lib
			json-lib
			2.4
		
		
		
			com.google.code.gson
			gson
			2.3.1
		
		
		
			commons-io
			commons-io
			1.4
		
		
			org.openoffice
			juh
			3.2.1
		
		
			org.openoffice
			ridl
			3.2.1
		
		
			org.openoffice
			unoil
			3.2.1
		
		
			
			commons-cli
			commons-cli
			1.1
			true
		
		
			org.hyperic
			sigar
			1.6.5.132
			true
		
		
			org.json
			json
			20090211
			true
		
		
			org.testng
			testng
			6.0.1
			test
		
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	


项目开始,要做的第一件事是下载文件,这里下载文件有一个要注意的地方

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第4张图片

我没有截全,因为文件的下载在这篇文章里不是重点,所以在这里不做详细记录,只要最后将文件存储到临时目录就行

文件下载完之后在进行文章的转换,这里我的转换规则:
1、图片不进行转换
2、文本文件转换编码为utf-8
3、office文件选择将word文档转为pdf文件,xls表格和ppt文件转为html文件,因为表格和ppt文件转换为pdf格式之后不太美观,所以选择将ppt转为html格式,后期取图片展示就可以了
4、压缩文件先解压到本地,然后运用Ztree插件做前端的展示。

由于涉及文件的操作,所以在这里一定要注意文件流的运用,用完了一定要及时关闭,还有文件的其他操作也要注意,比如文件地址的指向。当时我就是因为一个文件地址未仍指向一个操作中的目录导致后面临时文件的删除出错。

下面开始文件的转换,重点记录文本文件以及压缩文件的转换,当时在这花了较长时间,office文件的转换可以参照其他人写的。

文本文件的转换(这里要注意的是文本文件涉及到文件的编码问题,这里采用文本编码探测器进行探测):

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第5张图片

 

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第6张图片

文本探测器如下:

import org.mozilla.intl.chardet.nsDetector;
import org.mozilla.intl.chardet.nsICharsetDetectionObserver;

import java.io.*;

/**
 * Created by asus on 2017/12/28.
 */
public class FileCharsetDetector {

    /**
     * 传入一个文件(File)对象,检查文件编码
     *
     * @param file
     *            File对象实例
     * @return 文件编码,若无,则返回null
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static Observer guessFileEncoding(File file)
            throws FileNotFoundException, IOException {
        return guessFileEncoding(file, new nsDetector());
    }

    /**
     * 
     * 获取文件的编码
     * @param file
     *            File对象实例
     * @param languageHint
     *            语言提示区域代码 @see #nsPSMDetector ,取值如下:
     *             1 : Japanese
     *             2 : Chinese
     *             3 : Simplified Chinese
     *             4 : Traditional Chinese
     *             5 : Korean
     *             6 : Dont know(default)
     * 
* * @return 文件编码,eg:UTF-8,GBK,GB2312形式(不确定的时候,返回可能的字符编码序列);若无,则返回null * @throws FileNotFoundException * @throws IOException */ public static Observer guessFileEncoding(File file, int languageHint) throws FileNotFoundException, IOException { return guessFileEncoding(file, new nsDetector(languageHint)); } /** * 获取文件的编码 * * @param file * @param det * @return * @throws FileNotFoundException * @throws IOException */ private static Observer guessFileEncoding(File file, nsDetector det) throws FileNotFoundException, IOException { // new Observer Observer observer = new Observer(); // set Observer // The Notify() will be called when a matching charset is found. det.Init(observer); BufferedInputStream imp = new BufferedInputStream(new FileInputStream( file)); byte[] buf = new byte[1024]; int len; boolean done = false; boolean isAscii = false; while ((len = imp.read(buf, 0, buf.length)) != -1) { // Check if the stream is only ascii. isAscii = det.isAscii(buf, len); if (isAscii) { break; } // DoIt if non-ascii and not done yet. done = det.DoIt(buf, len, false); if (done) { break; } } imp.close(); det.DataEnd(); if (isAscii) { observer.encoding = "ASCII"; observer.found = true; } if (!observer.isFound()) { String[] prob = det.getProbableCharsets(); // // 这里将可能的字符集组合起来返回 // for (int i = 0; i < prob.length; i++) { // if (i == 0) { // encoding = prob[i]; // } else { // encoding += "," + prob[i]; // } // } if (prob.length > 0) { // 在没有发现情况下,去第一个可能的编码 observer.encoding = prob[0]; } else { return null; } } return observer; } /** * @Description: 文件字符编码观察者,但判断出字符编码时候调用 */ public static class Observer implements nsICharsetDetectionObserver { /** * @Fields encoding : 字符编码 */ private String encoding = null; /** * @Fields found : 是否找到字符集 */ private boolean found = false; @Override public void Notify(String charset) { this.encoding = charset; this.found = true; } public String getEncoding() { return encoding; } public boolean isFound() { return found; } @Override public String toString() { return "Observer [encoding=" + encoding + ", found=" + found + "]"; } } }

压缩文件转换(因为前端要生成文件树,所以在这里要先进行文件解压,在进行文件的读取,最终要生成的是一段字符串里面包含所有文件的信息):

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第7张图片

解压文件的操作这里也不详细记录了,很多网上的资料,这里记录一下文件树的生成,首先我们定义一个文件节点,里面包含子文件,文件名称,判断是否为文件夹以及文件绝对路径:

/**
     * 文件节点(区分文件上下级)
     */
    public static class FileNode{

        private String originName;
        private boolean directory;
        private String fullPath;

        private List childList;

        public FileNode(String originName, List childList, boolean directory, String fullPath) {
            this.originName = originName;
            this.childList = childList;
            this.directory = directory;
            this.fullPath = fullPath;

        }

        public String getFullPath() {
            return fullPath;
        }

        public void setFullPath(String fullPath) {
            this.fullPath = fullPath;
        }

        public List getChildList() {
            return childList;
        }

        public void setChildList(List childList) {
            this.childList = childList;
        }

        @Override
        public String toString() {
            try {
                return new ObjectMapper().writeValueAsString(this);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return "";
            }
        }

        public String getOriginName() {
            return originName;
        }

        public void setOriginName(String originName) {
            this.originName = originName;
        }

        public boolean isDirectory() {
            return directory;
        }

        public void setDirectory(boolean directory) {
            this.directory = directory;
        }
    }

 
/**
     * 通过递归得到某一路径下所有的目录及其文件
     */
    public static List getFiles(String filePath){
        File root = new File(filePath);
        File[] files = root.listFiles();
        String originName = "";
        boolean isDirectory = false;
        String fullPath = "";

        List fileNodes = new ArrayList<>();
        for(File file:files){

            List childList = new ArrayList<>();

            if(file.isDirectory()){
                isDirectory = true;
                originName = file.getName();
                fullPath = file.getAbsolutePath();
                childList = getFiles(file.getPath());
            } else {
                originName = file.getName();
                isDirectory = false;
                fullPath = file.getAbsolutePath();
            }
            // 进行转义,否则json解析不了
            fullPath = fullPath.replace("\\", "/");
            FileNode fileNode = new FileNode(originName, childList, isDirectory, fullPath);
            fileNodes.add(fileNode);
        }
        return fileNodes;
    }

这样我们就得到了文件树,前端的展示就简单多了,后面只需要把文件树转为字符串传到前端j就行了,注意这里的文件绝对路径的写法,默认是生成“\\”,这里要换成“/”。到这步,文件的转换基本就差不多了,剩下我们要做的就是文件的展示。这里还有一个地方需要注意的是,生成文件存储目录的时候增加一层目录用于区分唯一文件,这里我采用的是取文件的hash值,作为文件的上级存储目录,这样就不会有重复的文件目录了。


文件展示 :前面一直没有说Controller层如何写,这里开始说明

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第8张图片

 

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第9张图片

 

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第10张图片

 

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第11张图片

 

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第12张图片

原理就是转换完文件之后再定位到文件存放的目录,将本地文件以流的方式输出到页面。

这样写完之后便可以写页面了,页面显示规则:1、图片的显示可以用viewer.js插件(一个图片显示器,支持主流的图片显示操作),我这里直接写到页面上,后续再加上。2、pdf文件的显示可以用pdf.js插件。3、压缩文件显示用Ztree插件。4、ppt文件的显示这里推荐一个开源js,个人觉得还不错,点击打开链接。

最后,显示效果如下:

压缩文件:springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第13张图片
文档:

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第14张图片

报表:

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第15张图片

PPT文件:

springboot搭建文件预览解决方案,支持目前主流格式office文件,txt文件,png,jpg等图片以及压缩文件的在线预览功能_第16张图片

图片:

总结

个人项目可以采用和我一样的方式,写的有点乱,有问题欢迎在底部留言。最后附上项目地址:https://github.com/Chenchicheng/file_viewer。

你可能感兴趣的:(springboot)