Java實現Office線上預覽
阿新 • • 發佈:2019-01-30
上傳檔案是我們在開發中經常遇到的需求,而某些情況下,我們需要實現Office的線上預覽功能。
一.下載及安裝軟體
1.安裝OpenOffice軟體 ,該軟體的作用是將Office轉換為Pdf
該軟體是Apache旗下的一個免費的文書處理軟體,下載地址:Apache OpenOffice的連結
2.安裝Swftools軟體,作用是將Pdf轉換為Swf
3.安裝FlexPaper,該軟體的作用是解析並顯示SWF格式的檔案
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。