doc转swf,主流文档在线查看解决方案--类似百度文档功能
引言: 最近项目中对上传的文件需要在线查看功能(就是不用下载到本地,可以直接在网页里打开的查看),通过几周的研究终于搞定,在此总结下供有同样需求的同仁查询和使用。 原理: 通常的在线查看功能都是使用文档转换工具,把原始文档转换成swf文档,然后通过网页直接展示文档内容。 解决方案: 在前期技术研究的过程中,发现有三种解决方案,他们分别是: 1、使用 FlexPaper + Pdf2swf 组合。 缺点是只能提供pdf转换成swf然后在线查看。要支持其他格式的话,需要先转成pdf,这样的话效率有点低。不过网上这种方式的资料挺多的。 相关资料: www.cnblogs.com/luckyxiaoxuan/archive/2012/06/13/2548510.html 2、使用FlashPaper 把文档转成swf直接显示 这种方式的好处在于支持多种格式的文档转换,支持的文档格式包括(doc、docx、xls、xlsx、pdf、txt, ppt、pptx), ppt、pptx的支持效果不怎么好,转换有些慢,要支持这两种方式的话,有专有的转换工具。 原来准备使用FlashPaper转换成swf文档,然后使用FlexPaper显示的,但是发现使用FlexPaper显示FlashPaper转成的swf存在问题,不能显示swf内容,而且不停的闪。后来想起浏览器可以直接支持swf显示的。使用<object><embed>标签即可。 还有一个好处就是这个工具免费。 缺点就是: 最后版本2.2,发布于2008年5月,此后不再支持;支持winxp, server2003等,不支持win7系统; 3、使用Print2Flash把文档转换成swf直接显示 这个东西比FlashPaper更强大,功能更全面,而且提供各种系统的支持。是一个非常不错的工具。 缺点就是:需要money,有需求的公司可以使用。 相关资料: http://www.blue-pacific.com/print2flash/samples/default.htm 我的方案: 我选用的第二种方案,免费,而且对各种当前流行的文档都支持,同时服务器是window server 2003。下面说下具体的程序吧。 1、FlashPaper的安装 可以在网上下载 FlashPaper2.2绿色版,地址: http://download.csdn.net/detail/walkerjong/4420486 下载安装程序后,可以点击install.bat安装FlashPaper,若出现下面的错误: flashpaper AddPrinterDriver stage 13: error 126 - 找不到指定的模块 错误原因: 安装操作系统的时候没有开启系统还原功能,FlashPaper需要使用该功能。 解决方案: 把安装文件包里的srclient.dll文件拷贝到c:/windows/system32/目录下。 当然也可以使用java程序自动安装,下面是我的工具类代码:FlashPaperUtil.java package org.study.isap.common.util; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.apache.log4j.Logger; public class FlashPaperUtil { private static final Logger logger = Logger.getLogger(FlashPaperUtil.class); // flashPaper的存放位置 public static final String FLASH_PAPER_DIR = "bin/flashPaper2_2"; // 转换各种格式的文档为swf的命令 public static final String FLASH_PAPER_CMD = "FlashPrinter.exe"; // 检查swf是否转换完成的最大等待次数 private static final int maxWaitCount = 60; // 检查swf是否存在的时间间隔,单位ms。 private static final int checkInterval = 20000; private static final File flashPaperDir = initDir(); private FlashPaperUtil(){ } private static File initDir(){ File dir = new File(FileUtil.getWebRootPath(),FLASH_PAPER_DIR); logger.debug("flashPaperDir["+dir.getAbsolutePath()+"]"); return dir; } /** * 卸载flashPaper。 */ public static void uninstall(){ String uninstallCmd = "uninstall.bat"; try { String cmd =new File(flashPaperDir,uninstallCmd).getAbsolutePath(); Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(cmd,null,flashPaperDir); try { // 读取process输出流,放置buffer过小阻塞 InputStream infoStream = process.getInputStream(); new ReadThread(infoStream).start(); InputStream errorStream = process.getErrorStream(); new ReadThread(errorStream).start(); process.waitFor(); } catch (InterruptedException e) { logger.error(e); }finally{ process.destroy(); } runtime = null; logger.info("卸载FlashPaper成功,cmd["+cmd+"]"); } catch (IOException e) { logger.error(e); logger.error("卸载FlashPaper时出现错误。"); } } /** * 安装flashPaper。 */ public static void install(){ String installCmd = "install.bat"; if(checkInstallEnvironment()){ try { String cmd =new File(flashPaperDir,installCmd).getAbsolutePath(); Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(cmd,flashPaperDir); try { // 读取process输出流,放置buffer过小阻塞 InputStream infoStream = process.getInputStream(); new ReadThread(infoStream).start(); InputStream errorStream = process.getErrorStream(); new ReadThread(errorStream).start(); process.waitFor(); } catch (InterruptedException e) { logger.error(e); }finally{ process.destroy(); } runtime = null; logger.info("安装FlashPaper成功,cmd["+cmd+"]"); } catch (IOException e) { logger.error(e); logger.error("安装FlashPaper时出现错误。"); } } } /** * 检查安装flashPaper的环境。 * @return */ private static boolean checkInstallEnvironment(){ String systemRoot = System.getenv("SystemRoot"); File dest = new File(systemRoot,"system32/srclient.dll"); logger.debug("操作系统安装路径["+systemRoot+"]"); if(!dest.exists()){ logger.info("系统安装目录下不存在该文件["+dest.getAbsolutePath()+"],程序将自动复制该文件。"); String srcFile = "srclient.dll"; try { File src = new File(flashPaperDir,srcFile); FileUtil.copyFile(src,dest); return true; } catch (FileNotFoundException e) { logger.error("找不到要拷贝的源文件["+srcFile+"]",e); } catch (IOException e) { logger.error("复制文件出错, 源文件["+srcFile+"],目标文件["+dest.getAbsolutePath()+"]",e); } logger.error("您的环境不能自动安装FlashPaPer,需要手动安装,安装程序位置/WEB-INF/classes/"+FLASH_PAPER_DIR); return false; }else{ logger.info("系统安装目录下存在该文件["+dest.getAbsolutePath()+"],FlashPaper可以开始安装。"); return true; } } /** * 使用flashpaper将文档格式转换生产swf文件。 * 支持格式: office(word、excel),pdf, txt等主流格式。 * @param path * @return */ public static File fileToSwf(String input,String output){ File inputFile = new File(input); File outputFile = new File(output); return fileToSwf(inputFile,outputFile); } /** * 使用flashpaper将文档格式转换生产swf文件。 * 支持格式: office(word、excel),pdf, txt等主流格式。 * @param path * @return */ public static File fileToSwf(File input,File output){ return fileToSwf(input,output,true); } public static File fileToSwf(File input,File output,boolean waitFinished){ if(input == null || !input.exists()){ logger.error("要转换为swf的文件["+input.getAbsolutePath()+"]为空或不存在!"); return null; } if(output.exists()){ logger.info("swf["+output+"]已经存在。"); return output; } String printerCmd = new File(flashPaperDir,FLASH_PAPER_CMD).getAbsolutePath(); String cmd = printerCmd+" "+input.getAbsolutePath()+" -o "+output.getAbsolutePath(); logger.debug("fileToSwf cmd["+cmd+"]"); int resultCode = 1; try { Process process = Runtime.getRuntime().exec(cmd,flashPaperDir); try { // 读取process输出流,系统提供的buffer过小不读取会阻塞 new ReadThread(process.getInputStream()).start(); new ReadThread(process.getErrorStream()).start(); resultCode = process.waitFor(); if(resultCode == 1){ logger.error("转换文件过程中出现错误,请检查FlashPaper环境是否安装正确!"); } ?} catch (InterruptedException e) { logger.error(e); }finally{ process.destroy(); } if(resultCode != 1 && waitFinished){ for(int count=maxWaitCount; count>=0; count--){ if(output.exists()){ logger.info("转换文档为swf成功,swf["+output.getAbsolutePath()+"]"); break; }else{ try { // 休眠checkInterval秒后检查swf文件是否转换完成 Thread.sleep(checkInterval); } catch (InterruptedException e) { logger.error(e); } } } } } catch (IOException e) { logger.error("转换文档为swf失败,path["+input.getAbsolutePath()+"]",e); } return output; } private static class ReadThread extends Thread { private InputStream inputStream; public ReadThread(InputStream inputStream){ this.inputStream = inputStream; } public void run(){ BufferedReader input = null; String str = null; try { input = new BufferedReader(new InputStreamReader(this.inputStream,"GBK")); while( (str=input.readLine())!= null){ logger.debug(str); } } catch (IOException e) { logger.error("读取执行线程信息时出错",e); }finally{ try { input.close(); this.inputStream = null; } catch (IOException e) { logger.error(e); } } } } } 另外,为了方便程序部署,我们写了一个自动安装程序。 FlashPaperInstallService.java package org.study.isap.common.service; import org.springframework.stereotype.Service; import com.cosbulk.isap.common.util.FlashPaperUtil; @Service public class FlashPaperInstallService { public FlashPaperInstallService(){ Thread thread = new InstallThread(); thread.start(); } private static class InstallThread extends Thread { public InstallThread(){ setName("[Install FlashPaper Thread]"); setDaemon(true); } public void run(){ FlashPaperUtil.uninstall(); FlashPaperUtil.install(); } } } FileUtil.java 文件如下: package org.study.isap.common.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.springframework.util.StringUtils; public class FileUtil { private static final Logger logger = Logger.getLogger(FileUtil.class); // web工程的文件系统根目录 (/**/isap) private static final String webRootPath; // web工程的URL根目录 (http://***.**/isap) private static String webRootUrl; static { webRootPath = initWebFileBase(); webRootUrl = null; } private FileUtil(){ } private static String initWebFileBase(){ String fileBase = null; String path = FlashPaperUtil.class.getClassLoader().getResource("").getFile(); // 获取的文件路径为url地址编码,需要处理空格问题 String classPath = path; try { classPath = URLDecoder.decode(path,"UTF-8"); } catch (UnsupportedEncodingException e) { logger.error(e); } int index = classPath.lastIndexOf("/WEB-INF/classes"); if(index != -1){ fileBase = classPath.substring(0,index); logger.debug("获取isap文件系统根路径成功,webFileBase["+fileBase+"]"); }else{ index = classPath.lastIndexOf("/build/classes"); if(index != -1){ fileBase = classPath.substring(0,index)+"/WebRoot"; }else{ fileBase=""; logger.error("获取isap文件系统根路径错误。path["+classPath+"]"); } } return fileBase; } //------------------ 路径相关 ----------------- /** * 返回web工程的文件系统的绝对路径。 * @return */ public static String getWebRootPath(){ return webRootPath; } /** * 把相对webFileBase的path转换成url形式的字符串。 * 例如:<br/> * 输入: /uploadFiles/project/file/test.doc <br/> * 输出:http://127.0.0.1:8080/isap/uploadFiles/project/file/test.doc <br/> * @param request * @param path * @return */ public static String getDocUrl(HttpServletRequest request,String path){ if(!StringUtils.hasLength(webRootUrl)){ webRootUrl = request.getScheme()+"://"+request.getLocalAddr()+":"+request.getLocalPort()+request.getContextPath(); } if(StringUtils.hasLength(path)){ if(path.startsWith("http://")){ return path; } path = path.replace('','/'); }else{ return webRootUrl; } if(!path.startsWith("/")){ return webRootUrl+"/"+path; } return webRootUrl+path; } // ----------------------- 文件名和文件类型相关 ---------------- /** * 获取文件名称。 */ public static String getFileName(String docUrl){ int index = docUrl.lastIndexOf("/"); if(index != -1){ return docUrl.substring(index+1); }else{ return docUrl; } } /** * 获取文件类型,返回带点号的文件类型。例如“.doc” * * @param docUrl * @return */ public static String getFileType(String docUrl){ int index = docUrl.lastIndexOf("."); if(index != -1){ return docUrl.substring(index); }else{ return docUrl; } } /** * 获得输入路径下,同名文件的swf文件。 <br /> * * @param path * @param fileType * @return */ public static String getSwfFile(String path){ String swfPath = null; if(StringUtils.hasLength(path)){ int index = path.lastIndexOf("."); if(index != -1){ swfPath = path.substring(0,index)+".swf"; } } return swfPath; } public static File getSwfFile(File file) { String swfpath = getSwfFile(file.getAbsolutePath()); return new File(swfpath); } // ---------- 复制文件 --------- public static void copyFile(File src,File dest) throws IOException{ File dir = dest.getParentFile(); if(!dir.exists()){ dir.mkdirs(); } BufferedInputStream input = null; BufferedOutputStream output = null; try{ input = new BufferedInputStream(new FileInputStream(src)); output = new BufferedOutputStream(new FileOutputStream(dest)); int length = 0; byte[] buffer = new byte[4*1024]; while((length = input.read(buffer)) >= 0){ output.write(buffer,length); } }finally{ FileUtil.cloSEOutputStream(output); FileUtil.closeInputStream(input); } } // ------------- 关闭文件流 -------------------- /** * 关闭输入流。 * @param input */ public static void closeInputStream(InputStream input){ if(input != null){ try { input.close(); } catch (IOException e) { logger.error("关闭输入文件失败!"); logger.error(e); } } } /** * 关闭输出流。 * @param output */ public static void cloSEOutputStream(OutputStream output){ if(output != null){ try { output.close(); } catch (IOException e) { logger.error("关闭输出文件失败!"); logger.error(e); } } } } 说明: 下载下来的flashPaper安装程序解压后放置在 WebContent/bin/目录下。 程序自动的时候自动安装,若检测到没有使用系统还原功能,自动拷贝文件到系统system32目录下。 2、在上面贴出的代码中,使用FlashPaperUtil. fileToSwf()函数即可完成对可支持文档的转换。即转成swf文件。 3、显示转成成的swf文件。 displaySwf.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <%@ taglib prefix="c" uri="/WEB-INF/tld/c.tld" %> <% String webRoot = request.getContextPath(); %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <base href="<%=webRoot%>/view/common/" /> <title>在线显示文档</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <style type="text/css" media="screen"> html,body{ margin: 0px; padding: 0px; overflow: hidden; height: 100%; } #content{ width:100%; height:100%; MARGIN: 0px auto; } </style> </head> <body> <c:if test="${swfUrl!=null}"> <div id="content"> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,19,0" width="100%" height="100%" > <param name="movie" value="${swfUrl}" /> <param name="quality" value="high" /> <param name="allowFullScreen" value="true" /> <embed pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" src="${swfUrl}" allowfullscreen="true" quality="high" width="100%" height="100%" > </embed> </object> </div> </c:if> <c:if test="${swfUrl==null}"> <div class="box error center" style="width:60%;"> <h1>没有指定要显示的文档路径!</h1> </div> </c:if> </body> </html> 处理请求的controller类中相关方法: /** * 显示在线文档。 * @return */ @RequestMapping("show") public String show(String swfUrl,HttpServletRequest request){ request.setAttribute("swfUrl",swfUrl); return "common/displaySwf"; } 请求显示在线文档的url如下: http://localhost:8080/isap/fileManage/show.action?swfUrl=http://192.168.1.100/isap_doc/1341818769265.swf 注: 在FlashPaper转各类文档的时候,看到他们相关程序打开了要转的文件,然后转换的。所以碰到问题的时候注意检查一下几点: 1、服务器上是否安装相关文档的打开程序,例如office 2007? --> docx; 2、检查服务器上的Print Spoller服务是否启动,虚拟打印需要用到该服务; 3、还是失败的话,用cmd运行FlashPaper安装程序下的install.bat,查看错误原因。 ok,至此为止已经完成各种文档的转换和显示问题,希望能有同样需求的同仁们少走弯路。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |