上传文件是我们在开发中经常遇到的需求,而某些情况下,我们需要实现Office的在线预览功能。
一.下载及安装软件
1.安装OpenOffice软件 ,该软件的作用是将Office转换为Pdf
该软件是Apache旗下的一个免费的文字处理软件,下载地址:Apache OpenOffice的链接
2.安装Swftools软件,作用是将Pdf转换为Swf
下载链接:Swftools官网下载
3.安装FlexPaper,该软件的作用是解析并显示SWF格式的文件
下载链接:FlexPaper官网链接
4.执行完上述工作后,进入OpenOffice安装目录后启动OpenOffice服务
执行命令:soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
二.开发部分对应介绍
准备相应开发工具jar包
相关js包
如果选用pdfobject.js可选择不用FlexPaper的特性,因为该脚本就是为了动态加载pdf。
如果使用FlexPaper,必须将FlexPaperViewer.swf将客户端文件放在一起
项目lib完整jar包图:
辅助转换类DocConverter:
package com.itmyhome.util;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
/**
* doc docx格式转换
*/
public class DocConverter {
private static final int environment = 1;// 环境 1:windows 2:linux
private String fileString="";// (只涉及pdf2swf路径问题)
private String outputPath = "";// 输入路径 ,如果不设置就输出在默认的位置
private String fileName="";
private File pdfFile=null;
private File swfFile=null;
private File docFile=null;
public DocConverter(String fileString) {
ini(fileString);
}
/*
*重新设置file
*
* @param fileString
*/
public void setFile(String fileString) {
ini(fileString);
}
/**
* 初始化
*
* @param fileString
*/
private void ini(String fileString) {
this.fileString = fileString;
fileName = fileString.substring(0, fileString.lastIndexOf("."));
docFile = new File(fileString);
pdfFile = new File(fileName + ".pdf");
swfFile = new File(fileName + ".swf");
}
/**
* 转为PDF
* OpenOffice的作用是将office转换为pdf
* @param
*/
private void doc2pdf() throws Exception {
if (docFile.exists()) {
if (!pdfFile.exists()) {
//启动OpenOffice服务 soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
try {
connection.connect();
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(docFile, pdfFile);
// close the connection
connection.disconnect();
System.out.println("****pdf转换成功,PDF输出:" + pdfFile.getPath()+ "****");
} catch (java.net.ConnectException e) {
e.printStackTrace();
System.out.println("****swf转换器异常,openoffice服务未启动!****");
throw e;
} catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {
e.printStackTrace();
System.out.println("****swf转换器异常,读取转换文件失败****");
throw e;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
} else {
System.out.println("****已经转换为pdf,不需要再进行转化****");
}
} else {
System.out.println("****swf转换器异常,需要转换的文档不存在,无法转换****");
}
}
/**
* 转换成 swf
* swftools是将pdf转换为swf
*/
@SuppressWarnings("unused")
private void pdf2swf() throws Exception {
Runtime r = Runtime.getRuntime();
if (!swfFile.exists()) {
if (pdfFile.exists()) {
if (environment == 1) {// windows环境处理
try {
Process p = r.exec("D:/swftools/pdf2swf.exe "+ pdfFile.getPath() + " -o "+ swfFile.getPath() + " -T 9");
System.out.println(loadStream(p.getInputStream()));
System.err.println(loadStream(p.getErrorStream()));
System.out.println(loadStream(p.getInputStream()));
System.err.println("****swf转换成功,文件输出:"
+ swfFile.getPath() + "****");
/*if (pdfFile.exists()) {
pdfFile.delete();
}*/
} catch (IOException e) {
e.printStackTrace();
throw e;
}
} else if (environment == 2) {// linux环境处理
try {
Process p = r.exec("pdf2swf " + pdfFile.getPath()
+ " -o " + swfFile.getPath() + " -T 9");
System.out.print(loadStream(p.getInputStream()));
System.err.print(loadStream(p.getErrorStream()));
System.err.println("****swf转换成功,文件输出:"
+ swfFile.getPath() + "****");
if (pdfFile.exists()) {
pdfFile.delete();
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
} else {
System.out.println("****pdf不存在,无法转换****");
}
} else {
System.out.println("****swf已经存在不需要转换****");
}
}
static String loadStream(InputStream in) throws IOException {
int ptr = 0;
in = new BufferedInputStream(in);
StringBuffer buffer = new StringBuffer();
while ((ptr = in.read()) != -1) {
buffer.append((char) ptr);
}
return buffer.toString();
}
/**
* 转换主方法
*/
@SuppressWarnings("unused")
public boolean conver() {
if (swfFile.exists()) {
System.out.println("****swf转换器开始工作,该文件已经转换为swf****");
return true;
}
if (environment == 1) {
System.out.println("****swf转换器开始工作,当前设置运行环境windows****");
} else {
System.out.println("****swf转换器开始工作,当前设置运行环境linux****");
}
try {
doc2pdf();
pdf2swf();
} catch (Exception e) {
e.printStackTrace();
return false;
}
if (swfFile.exists()) {
return true;
} else {
return false;
}
}
/**
* 返回文件路径
*
* @param
*/
public String getswfPath() {
if (swfFile.exists()) {
String tempString = swfFile.getPath();
tempString = tempString.replaceAll("\\\\", "/");
return tempString;
} else {
return "";
}
}
/**
* 设置输出路径
*/
public void setOutputPath(String outputPath) {
this.outputPath = outputPath;
if (!outputPath.equals("")) {
String realName = fileName.substring(fileName.lastIndexOf("/"),
fileName.lastIndexOf("."));
if (outputPath.charAt(outputPath.length()) == '/') {
swfFile = new File(outputPath + realName + ".swf");
} else {
swfFile = new File(outputPath + realName + ".swf");
}
}
}
}
文件上传和接口调用类 FileController:
package com.itmyhome.web;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.itmyhome.util.DocConverter;
public class FileController extends HttpServlet {
private static final long serialVersionUID = 1L;
// 保存文件的目录
private static String PATH_FOLDER = "/";
// 存放临时文件的目录
private static String TEMP_FOLDER = "/";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获得磁盘文件条目工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 如果没以下两行设置的话,上传大的 文件 会占用 很多内存,
// 设置暂时存放的 存储室 , 这个存储室,可以和 最终存储文件 的目录不同
/**
* 原理 它是先存到 暂时存储室,然后在真正写到 对应目录的硬盘上, 按理来说 当上传一个文件时,其实是上传了两份,第一个是以 .tem
* 格式的 然后再将其真正写到 对应目录的硬盘上
*/
factory.setRepository(new File(TEMP_FOLDER));
// 设置 缓存的大小,当上传文件的容量超过该缓存时,直接放到 暂时存储室
factory.setSizeThreshold(1024 * 1024);
// 高水平的API文件上传处理
ServletFileUpload upload = new ServletFileUpload(factory);
// 提交上来的信息都在这个list里面
// 这意味着可以上传多个文件
// 请自行组织代码
try{
@SuppressWarnings("unchecked")
List<FileItem> list = upload.parseRequest(request);
// 获取上传的文件
FileItem item = getUploadFileItem(list);
// 获取文件名
String filename = getUploadFileName(item);
String filetype = filename.substring(filename.lastIndexOf(".") + 1,
filename.length());
filename = Long.toString(System.currentTimeMillis()) + "."
+ filetype;
System.out.println("存放目录:" + PATH_FOLDER);
System.out.println("文件名:" + filename);
// 真正写到磁盘上
item.write(new File(PATH_FOLDER, filename)); // 第三方提供的
String newDir = Long.toString(System.currentTimeMillis());
//调用转换类DocConverter,并将需要转换的文件传递给该类的构造方法
DocConverter d = new DocConverter(PATH_FOLDER + "/" + filename);
//调用conver方法开始转换,先执行doc2pdf()将office文件转换为pdf;再执行pdf2swf()将pdf转换为swf;
d.conver();
System.out.println(d.getswfPath());
//生成swf相对路径,以便传递给flexpaper播放器
String swfpath = "upload"+d.getswfPath().substring(d.getswfPath().lastIndexOf("/"));
System.out.println(swfpath);
//将相对路径放入sessio中保存
String pdfpath=swfpath.substring(0, swfpath.lastIndexOf(".")+1)+"pdf";
Map map=new HashMap();
map.put("swfpath", swfpath);
map.put("pdfpath", pdfpath);
HttpSession session=request.getSession();
session.setAttribute("path", map);
File file = new File(PATH_FOLDER+"/"+filename);
file.delete();
}catch (Exception e) {
// TODO: handle exception
response.sendRedirect("upload_error.jsp");
}finally{
request.getRequestDispatcher("/upload_ok.jsp").forward(request, response);
}
}
@Override
public void init(ServletConfig config) throws ServletException {
ServletContext servletCtx = config.getServletContext();
// 初始化路径
// 保存文件的目录
PATH_FOLDER = servletCtx.getRealPath("upload");
// 存放临时文件的目录,存放xxx.tmp文件的目录
TEMP_FOLDER = servletCtx.getRealPath("uploadTemp");
}
private FileItem getUploadFileItem(List<FileItem> list) {
for (FileItem fileItem : list) {
if (!fileItem.isFormField()) {
return fileItem;
}
}
return null;
}
private String getUploadFileName(FileItem item) {
// 获取路径名
String value = item.getName();
// 索引到最后一个反斜杠
int start = value.lastIndexOf("/");
// 截取 上传文件的 字符串名字,加1是 去掉反斜杠,
String filename = value.substring(start + 1);
return filename;
}
}
使用pdf.js方案的代码和效果图如下:
使用OpenOffice方案的代码和效果图如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%
Map map=(Map)session.getAttribute("path");
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>预览文件</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/flexpaper_flash.js"></script>
<script type="text/javascript" src="js/flexpaper_flash_debug.js"></script>
<!-- <script type="text/javascript" src="js/swfobject.js"></script> -->
<script type="text/javascript" src="js/pdfobject.js"></script>
<style type="text/css" media="screen">
html, body { height:100%; }
body { margin:0; padding:0; overflow:auto; }
#flashContent { display:none; }
</style>
</head>
<body>
<div style="position:absolute;left:50px;top:10px;">
<a id="viewerPlaceHolder" style="width:820px;height:650px;display:block"></a>
<script type="text/javascript">
var fp = new FlexPaperViewer(
'FlexPaperViewer',
'viewerPlaceHolder', { config : {
SwfFile : escape('<%=map.get("swfpath")%>'),
Scale : 0.6,
ZoomTransition : 'easeOut',//变焦过渡
ZoomTime : 0.5,
ZoomInterval : 0.2,//缩放滑块-移动的缩放基础[工具栏]
FitPageOnLoad : true,//自适应页面
FitWidthOnLoad : true,//自适应宽度
FullScreenAsMaxWindow : false,//全屏按钮-新页面全屏[工具栏]
ProgressiveLoading : false,//分割加载
MinZoomSize : 0.2,//最小缩放
MaxZoomSize : 3,//最大缩放
SearchMatchAll : true,
InitViewMode : 'Portrait',//初始显示模式(SinglePage,TwoPage,Portrait)
ViewModeToolsVisible : true,//显示模式工具栏是否显示
ZoomToolsVisible : true,//缩放工具栏是否显示
NavToolsVisible : true,//跳页工具栏
CursorToolsVisible : false,
SearchToolsVisible : true,
PrintPaperAsBitmap:false,
localeChain: 'en_US'
}});
</script>
</div>
</body>
</html>
总结:
因为OpenOffice目前不是完全开源,一次性能够处理的Office有限,小编建议使用pdf.js。
版权声明:本文为tmac937436原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。