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

Posted FighterLiu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中如何实现文件预览的功能相关的知识,希望对你有一定的参考价值。

文件预览方法总结

前言

日常开发中常见的文件格式有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中的代码如下:
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
下载完成后放入到项目中,如下:

在项目中新建一个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

请问JAVA如何实现打印及打印预览功能?

内容如题(此为桌面应用程序,非JSP)开发环境 JDK1.5 JBulider2006请给出详细源码,以及注释谢谢

package com.szallcom.tools;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;

import wf.common.SystemProperties;

public class PrintPreviewDialog extends JDialog implements ActionListener

private JButton nextButton = new JButton("Next");
private JButton previousButton = new JButton("Previous");
private JButton closeButton = new JButton("Close");
private JPanel buttonPanel = new JPanel();
private PreviewCanvas canvas;

public PrintPreviewDialog(Frame parent, String title, boolean modal,
PrintTest pt, String str)
super(parent, title, modal);
canvas = new PreviewCanvas(pt, str);
setLayout();


private void setLayout()
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(canvas, BorderLayout.CENTER);

nextButton.setMnemonic('N');
nextButton.addActionListener(this);
buttonPanel.add(nextButton);
previousButton.setMnemonic('N');
previousButton.addActionListener(this);
buttonPanel.add(previousButton);
closeButton.setMnemonic('N');
closeButton.addActionListener(this);
buttonPanel.add(closeButton);
this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
this.setBounds((int) ((SystemProperties.SCREEN_WIDTH - 400) / 2),
(int) ((SystemProperties.SCREEN_HEIGHT - 400) / 2), 400, 400);


public void actionPerformed(ActionEvent evt)
Object src = evt.getSource();
if (src == nextButton)
nextAction();
else if (src == previousButton)
previousAction();
else if (src == closeButton)
closeAction();


private void closeAction()
this.setVisible(false);
this.dispose();


private void nextAction()
canvas.viewPage(1);


private void previousAction()
canvas.viewPage(-1);


class PreviewCanvas extends JPanel
private String printStr;
private int currentPage = 0;
private PrintTest preview;

public PreviewCanvas(PrintTest pt, String str)
printStr = str;
preview = pt;


public void paintComponent(Graphics g)
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
PageFormat pf = PrinterJob.getPrinterJob().defaultPage();

double xoff;
double yoff;
double scale;
double px = pf.getWidth();
double py = pf.getHeight();
double sx = getWidth() - 1;
double sy = getHeight() - 1;
if (px / py < sx / sy)
scale = sy / py;
xoff = 0.5 * (sx - scale * px);
yoff = 0;
else
scale = sx / px;
xoff = 0;
yoff = 0.5 * (sy - scale * py);

g2.translate((float) xoff, (float) yoff);
g2.scale((float) scale, (float) scale);

Rectangle2D page = new Rectangle2D.Double(0, 0, px, py);
g2.setPaint(Color.white);
g2.fill(page);
g2.setPaint(Color.black);
g2.draw(page);

try
preview.print(g2, pf, currentPage);
catch (PrinterException pe)
g2.draw(new Line2D.Double(0, 0, px, py));
g2.draw(new Line2D.Double(0, px, 0, py));



public void viewPage(int pos)
int newPage = currentPage + pos;
if (0 <= newPage && newPage < preview.getPagesCount(printStr))
currentPage = newPage;
repaint();





package wf.common;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;

public final class SystemProperties

public static final double SCREEN_WIDTH = Toolkit.getDefaultToolkit().getScreenSize().getWidth();
public static final double SCREEN_HEIGHT = Toolkit.getDefaultToolkit().getScreenSize().getHeight();
public static final String USER_DIR = System.getProperty("user.dir");
public static final String USER_HOME = System.getProperty("user.home");
public static final String USER_NAME = System.getProperty("user.name");
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static final String PATH_SEPARATOR = System.getProperty("path.separator");
public static final String JAVA_HOME = System.getProperty("java.home");
public static final String JAVA_VENDOR = System.getProperty("java.vendor");
public static final String JAVA_VENDOR_URL = System.getProperty("java.vendor.url");
public static final String JAVA_VERSION = System.getProperty("java.version");
public static final String JAVA_CLASS_PATH = System.getProperty("java.class.path");
public static final String JAVA_CLASS_VERSION = System.getProperty("java.class.version");
public static final String OS_NAME = System.getProperty("os.name");
public static final String OS_ARCH = System.getProperty("os.arch");
public static final String OS_VERSION = System.getProperty("os.version");
public static final String[] FONT_NAME_LIST = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
public static final Font[] FONT_LIST = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
参考技术A 猪哥解答:
我这里有以前收藏的代码,两个类实现了简易的文本打印机的功能,包括预览。简单跟你说一下。
1、PrinterDemo.java主体类,也是入口类,里面有main方法可以直接在Eclipse中调试运行,他实现了从本地磁盘读取文本类文件打印以及打印预览的功能,其中File动作按钮中的PrintPreviw就是打印预览功能,你可以运行看看。
2、PrintPreview.java打印预览类,这是专门为预览打印设计的类,通过他的构造方法可以构造出一个预览类,PrinterDemo中的预览功能就是调用了这个类。

两个类放在同一个包下。

提交不上去,我把源码贴上来提交不了,字数也没有超标。你留一个邮箱,或者等我的文库上传的源码吧,我放到文库里,还在审批。

问题补充:档案已经上传到文库里了,地址是
DOC格式的:http://wenku.baidu.com/view/048ae0e8856a561252d36fab.html
PDF格式的:http://wenku.baidu.com/view/67c57a69011ca300a6c390fd.html
你下来看看吧。

以上是关于Java中如何实现文件预览的功能的主要内容,如果未能解决你的问题,请参考以下文章

如何用 Java 实现 wordexcel 等文档在线预览?

快速实现wordexcelppttxt等办公文件在线预览功能(Java版)

Java实现文件的预览

一个超牛逼的 Java 文件在线预览项目

一个超牛逼的 Java 文件在线预览项目

github掘金:一个超赞的 Java 文件在线预览项目