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 等文档在线预览?