doc转swf,主流文档在线查看解决方案-相仿百度文档功能

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

 

[java] view plaincopy
  1. package org.study.isap.common.util;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.File;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.InputStreamReader;  
  9.   
  10. import org.apache.log4j.Logger;  
  11.   
  12. public class FlashPaperUtil {  
  13.       
  14.     private static final Logger logger = Logger.getLogger(FlashPaperUtil.class);  
  15.       
  16.     // flashPaper的存放位置  
  17.     public static final String FLASH_PAPER_DIR = "bin/flashPaper2_2";  
  18.       
  19.     // 转换各种格式的文档为swf的命令  
  20.     public static final String FLASH_PAPER_CMD = "FlashPrinter.exe";  
  21.       
  22.     // 检查swf是否转换完成的最大等待次数  
  23.     private static final int maxWaitCount = 60;  
  24.       
  25.     // 检查swf是否存在的时间间隔, 单位ms。  
  26.     private static final int checkInterval = 20000;   
  27.           
  28.     private static final File flashPaperDir = initDir();  
  29.       
  30.     private FlashPaperUtil(){  
  31.     }  
  32.       
  33.     private static File initDir(){  
  34.         File dir = new File(FileUtil.getWebRootPath(), FLASH_PAPER_DIR);  
  35.         logger.debug("flashPaperDir["+dir.getAbsolutePath()+"]");  
  36.         return dir;  
  37.     }  
  38.           
  39.     /** 
  40.      * 卸载flashPaper。 
  41.      */  
  42.     public static void uninstall(){  
  43.         String uninstallCmd = "uninstall.bat";  
  44.         try {  
  45.             String cmd =new File(flashPaperDir, uninstallCmd).getAbsolutePath();  
  46.             Runtime runtime = Runtime.getRuntime();  
  47.             Process process = runtime.exec(cmd, null, flashPaperDir);  
  48.             try {  
  49.                 // 读取process输出流,放置buffer过小阻塞  
  50.                 InputStream infoStream = process.getInputStream();  
  51.                 new ReadThread(infoStream).start();  
  52.                 InputStream errorStream = process.getErrorStream();  
  53.                 new ReadThread(errorStream).start();  
  54.                 process.waitFor();  
  55.             } catch (InterruptedException e) {  
  56.                 logger.error(e);  
  57.             }finally{  
  58.                 process.destroy();  
  59.             }  
  60.             runtime = null;  
  61.             logger.info("卸载FlashPaper成功,cmd["+cmd+"]");  
  62.         } catch (IOException e) {  
  63.             logger.error(e);  
  64.             logger.error("卸载FlashPaper时出现错误。");  
  65.         }  
  66.     }  
  67.       
  68.     /** 
  69.      * 安装flashPaper。 
  70.      */  
  71.     public static void install(){  
  72.         String installCmd = "install.bat";  
  73.         if(checkInstallEnvironment()){  
  74.             try {  
  75.                 String cmd =new File(flashPaperDir, installCmd).getAbsolutePath();  
  76.                 Runtime runtime = Runtime.getRuntime();  
  77.                 Process process = runtime.exec(cmd, null, flashPaperDir);  
  78.                 try {  
  79.                     // 读取process输出流,放置buffer过小阻塞  
  80.                     InputStream infoStream = process.getInputStream();  
  81.                     new ReadThread(infoStream).start();  
  82.                     InputStream errorStream = process.getErrorStream();  
  83.                     new ReadThread(errorStream).start();  
  84.                     process.waitFor();        
  85.                 } catch (InterruptedException e) {  
  86.                     logger.error(e);  
  87.                 }finally{  
  88.                     process.destroy();  
  89.                 }  
  90.                 runtime = null;  
  91.                 logger.info("安装FlashPaper成功,cmd["+cmd+"]");  
  92.             } catch (IOException e) {  
  93.                 logger.error(e);  
  94.                 logger.error("安装FlashPaper时出现错误。");  
  95.             }  
  96.         }  
  97.     }  
  98.       便民养生网站长提供:http://www.yangsheng52.com/
  99.     /** 
  100.      * 检查安装flashPaper的环境。 
  101.      * @return 
  102.      */  
  103.     private static boolean checkInstallEnvironment(){  
  104.         String systemRoot = System.getenv("SystemRoot");  
  105.         File dest = new File(systemRoot, "system32/srclient.dll");  
  106.         logger.debug("操作系统安装路径["+systemRoot+"]");  
  107.         if(!dest.exists()){  
  108.             logger.info("系统安装目录下不存在该文件["+dest.getAbsolutePath()+"],程序将自动复制该文件。");  
  109.             String srcFile = "srclient.dll";  
  110.             try {  
  111.                 File src = new File(flashPaperDir, srcFile);  
  112.                 FileUtil.copyFile(src, dest);  
  113.                 return true;  
  114.             } catch (FileNotFoundException e) {  
  115.                 logger.error("找不到要拷贝的源文件["+srcFile+"]", e);  
  116.             } catch (IOException e) {  
  117.                 logger.error("复制文件出错, 源文件["+srcFile+"], 目标文件["+dest.getAbsolutePath()+"]", e);  
  118.             }  
  119.             logger.error("您的环境不能自动安装FlashPaPer,需要手动安装,安装程序位置/WEB-INF/classes/"+FLASH_PAPER_DIR);  
  120.             return false;  
  121.         }else{  
  122.             logger.info("系统安装目录下存在该文件["+dest.getAbsolutePath()+"],FlashPaper可以开始安装。");  
  123.             return true;  
  124.         }  
  125.     }  
  126.       
  127.     /** 
  128.      * 使用flashpaper将文档格式转换生产swf文件。 
  129.      * 支持格式: office(word、excel),pdf, txt等主流格式。 
  130.      * @param path 
  131.      * @return 
  132.      */  
  133.     public static File fileToSwf(String input, String output){  
  134.         File inputFile = new File(input);  
  135.         File outputFile = new File(output);  
  136.         return fileToSwf(inputFile, outputFile);  
  137.     }  
  138.       
  139.     /** 
  140.      * 使用flashpaper将文档格式转换生产swf文件。 
  141.      * 支持格式: office(word、excel),pdf, txt等主流格式。 
  142.      * @param path 
  143.      * @return 
  144.      */  
  145.     public static File fileToSwf(File input, File output){  
  146.         return fileToSwf(input, output, true);  
  147.     }  
  148.       
  149.     public static File fileToSwf(File input, File output, boolean waitFinished){  
  150.         if(input == null || !input.exists()){  
  151.             logger.error("要转换为swf的文件["+input.getAbsolutePath()+"]为空或不存在!");  
  152.             return null;  
  153.         }  
  154.         if(output.exists()){  
  155.             logger.info("swf["+output+"]已经存在。");  
  156.             return output;  
  157.         }  
  158.         String printerCmd = new File(flashPaperDir, FLASH_PAPER_CMD).getAbsolutePath();  
  159.         String cmd = printerCmd+" "+input.getAbsolutePath()+" -o "+output.getAbsolutePath();  
  160.         logger.debug("fileToSwf cmd["+cmd+"]");  
  161.         int resultCode = 1;  
  162.                 try {  
  163.             Process process = Runtime.getRuntime().exec(cmd, null, flashPaperDir);  
  164.             try {  
  165.                 // 读取process输出流,系统提供的buffer过小不读取会阻塞  
  166.                 new ReadThread(process.getInputStream()).start();  
  167.                 new ReadThread(process.getErrorStream()).start();  
  168.                 resultCode = process.waitFor();  
  169.                                 if(resultCode == 1){  
  170.                                       logger.error("转换文件过程中出现错误,请检查FlashPaper环境是否安装正确!");  
  171.                                }  
  172.                         } catch (InterruptedException e) {  
  173.                 logger.error(e);  
  174.             }finally{  
  175.                 process.destroy();  
  176.             }  
  177.             if(resultCode != 1 && waitFinished){  
  178.                 for(int count=maxWaitCount; count>=0; count--){  
  179.                     if(output.exists()){  
  180.                         logger.info("转换文档为swf成功,swf["+output.getAbsolutePath()+"]");  
  181.                         break;  
  182.                     }else{  
  183.                         try {   // 休眠checkInterval秒后检查swf文件是否转换完成  
  184.                             Thread.sleep(checkInterval);  
  185.                         } catch (InterruptedException e) {  
  186.                             logger.error(e);  
  187.                         }  
  188.                     }  
  189.                 }  
  190.             }  
  191.         } catch (IOException e) {  
  192.             logger.error("转换文档为swf失败, path["+input.getAbsolutePath()+"]", e);  
  193.         }  
  194.         return output;  
  195.     }  
  196.       
  197.     private static class ReadThread extends Thread {  
  198.         private InputStream inputStream;  
  199.           
  200.         public ReadThread(InputStream inputStream){  
  201.             this.inputStream = inputStream;  
  202.         }  
  203.           
  204.         public void run(){  
  205.             BufferedReader input = null;  
  206.             String str = null;  
  207.             try {  
  208.                 input = new BufferedReader(new InputStreamReader(this.inputStream, "GBK"));  
  209.                 while( (str=input.readLine())!= null){  
  210.                     logger.debug(str);  
  211.                 }  
  212.             } catch (IOException e) {  
  213.                 logger.error("读取执行线程信息时出错", e);  
  214.             }finally{  
  215.                 try {  
  216.                     input.close();  
  217.                     this.inputStream = null;  
  218.                 } catch (IOException e) {  
  219.                     logger.error(e);  
  220.                 }  
  221.             }  
  222.         }  
  223.     }     
  224. }  

 

另外,为了方便程序部署,我们写了一个自动安装程序。

FlashPaperInstallService.java

 

[java] view plaincopy
  1. package org.study.isap.common.service;  
  2.   
  3. import org.springframework.stereotype.Service;  
  4.   
  5. import com.cosbulk.isap.common.util.FlashPaperUtil;  
  6.   
  7. @Service  
  8. public class FlashPaperInstallService {  
  9.   
  10.     public FlashPaperInstallService(){  
  11.         Thread thread = new InstallThread();  
  12.         thread.start();  
  13.     }  
  14.       
  15.     private static class InstallThread extends Thread {  
  16.           
  17.         public InstallThread(){  
  18.             setName("[Install FlashPaper Thread]");  
  19.             setDaemon(true);  
  20.         }  
  21.           
  22.         public void run(){  
  23.             FlashPaperUtil.uninstall();  
  24.             FlashPaperUtil.install();  
  25.         }  
  26.     }  
  27. }  



 

 

 

FileUtil.java 文件如下:

 

[java] view plaincopy
  1. package org.study.isap.common.util;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.File;  
  6. import java.io.FileInputStream;  
  7. import java.io.FileOutputStream;  
  8. import java.io.IOException;  
  9. import java.io.InputStream;  
  10. import java.io.OutputStream;  
  11. import java.io.UnsupportedEncodingException;  
  12. import java.net.URLDecoder;  
  13.   
  14. import javax.servlet.http.HttpServletRequest;  
  15.   
  16. import org.apache.log4j.Logger;  
  17. import org.springframework.util.StringUtils;  
  18.   
  19. public class FileUtil {  
  20.     private static final Logger logger = Logger.getLogger(FileUtil.class);  
  21.       
  22.     // web工程的文件系统根目录 (/**/isap)  
  23.     private static final String webRootPath;  
  24.     // web工程的URL根目录 (http://***.**/isap)  
  25.     private static String webRootUrl;  
  26.       
  27.     static {  
  28.         webRootPath = initWebFileBase();  
  29.         webRootUrl = null;  
  30.     }  
  31.       
  32.     private FileUtil(){  
  33.           
  34.     }  
  35.       
  36.     private static String initWebFileBase(){  
  37.         String fileBase = null;  
  38.         String path = FlashPaperUtil.class.getClassLoader().getResource("").getFile();  
  39.         // 获取的文件路径为url地址编码,需要处理空格问题  
  40.         String classPath = path;  
  41.         try {  
  42.             classPath = URLDecoder.decode(path, "UTF-8");  
  43.         } catch (UnsupportedEncodingException e) {  
  44.             logger.error(e);  
  45.         }  
  46.         int index = classPath.lastIndexOf("/WEB-INF/classes");  
  47.         if(index != -1){  
  48.             fileBase = classPath.substring(0, index);  
  49.             logger.debug("获取isap文件系统根路径成功, webFileBase["+fileBase+"]");  
  50.         }else{  
  51.             index = classPath.lastIndexOf("/build/classes");  
  52.             if(index != -1){  
  53.                 fileBase = classPath.substring(0, index)+"/WebRoot";  
  54.             }else{  
  55.                 fileBase="";  
  56.                 logger.error("获取isap文件系统根路径错误。path["+classPath+"]");  
  57.             }  
  58.         }  
  59.         return fileBase;  
  60.     }  
  61.       
  62.     //------------------ 路径相关 -----------------  
  63.     /** 
  64.      * 返回web工程的文件系统的绝对路径。 
  65.      * @return 
  66.      */  
  67.     public static String getWebRootPath(){  
  68.         return webRootPath;  
  69.     }  
  70.       
  71.     /** 
  72.      * 把相对webFileBase的path转换成url形式的字符串。 
  73.      * 例如:<br/> 
  74.      * 输入: /uploadFiles/project/file/test.doc <br/> 
  75.      * 输出:http://127.0.0.1:8080/isap/uploadFiles/project/file/test.doc <br/> 
  76.      * @param request 
  77.      * @param path 
  78.      * @return 
  79.      */  
  80.     public static String getDocUrl(HttpServletRequest request, String path){  
  81.         if(!StringUtils.hasLength(webRootUrl)){  
  82.             webRootUrl = request.getScheme()+"://"+request.getLocalAddr()+":"+request.getLocalPort()+request.getContextPath();  
  83.         }  
  84.         if(StringUtils.hasLength(path)){  
  85.             if(path.startsWith("http://")){  
  86.                 return path;  
  87.             }  
  88.             path = path.replace('\\', '/');  
  89.         }else{  
  90.             return webRootUrl;  
  91.         }  
  92.         if(!path.startsWith("/")){  
  93.             return webRootUrl+"/"+path;  
  94.         }  
  95.         return webRootUrl+path;  
  96.     }  
  97.       
  98.     // ----------------------- 文件名和文件类型相关 ----------------  
  99.     /** 
  100.      * 获取文件名称。 
  101.      */  
  102.     public static String getFileName(String docUrl){  
  103.         int index = docUrl.lastIndexOf("/");  
  104.         if(index != -1){  
  105.             return docUrl.substring(index+1);  
  106.         }else{  
  107.             return docUrl;  
  108.         }  
  109.     }  
  110.     /** 
  111.      * 获取文件类型, 返回带点号的文件类型。例如“.doc” 
  112.      *  
  113.      * @param docUrl 
  114.      * @return 
  115.      */  
  116.     public static String getFileType(String docUrl){  
  117.         int index = docUrl.lastIndexOf(".");  
  118.         if(index != -1){  
  119.             return docUrl.substring(index);  
  120.         }else{  
  121.             return docUrl;  
  122.         }  
  123.     }  
  124.       
  125.     /** 
  126.      * 获得输入路径下,同名文件的swf文件。 <br /> 
  127.      *  
  128.      * @param path 
  129.      * @param fileType 
  130.      * @return 
  131.      */  
  132.     public static String getSwfFile(String path){  
  133.         String swfPath = null;  
  134.         if(StringUtils.hasLength(path)){  
  135.             int index = path.lastIndexOf(".");  
  136.             if(index != -1){  
  137.                 swfPath = path.substring(0, index)+".swf";  
  138.             }  
  139.         }  
  140.         return swfPath;  
  141.     }  
  142.       
  143.     public static File getSwfFile(File file) {  
  144.         String swfpath = getSwfFile(file.getAbsolutePath());  
  145.         return new File(swfpath);  
  146.     }  
  147.       
  148.     // ---------- 复制文件 ---------  
  149.     public static void copyFile(File src, File dest) throws IOException{  
  150.         File dir = dest.getParentFile();  
  151.         if(!dir.exists()){  
  152.             dir.mkdirs();  
  153.         }  
  154.         BufferedInputStream input = null;   
  155.         BufferedOutputStream output = null;  
  156.         try{  
  157.             input = new BufferedInputStream(new FileInputStream(src));  
  158.             output = new BufferedOutputStream(new FileOutputStream(dest));  
  159.             int length = 0;  
  160.             byte[] buffer = new byte[4*1024];  
  161.             while((length = input.read(buffer)) >= 0){  
  162.                 output.write(buffer, 0, length);  
  163.             }  
  164.         }finally{  
  165.             FileUtil.closeOutputStream(output);  
  166.             FileUtil.closeInputStream(input);  
  167.         }  
  168.     }  
  169.       
  170.     // ------------- 关闭文件流 --------------------  
  171.     /** 
  172.      * 关闭输入流。 
  173.      * @param input 
  174.      */  
  175.     public static void closeInputStream(InputStream input){  
  176.         if(input != null){  
  177.             try {  
  178.                 input.close();  
  179.             } catch (IOException e) {  
  180.                 logger.error("关闭输入文件失败!");  
  181.                 logger.error(e);  
  182.             }  
  183.         }  
  184.     }  
  185.       
  186.     /** 
  187.      * 关闭输出流。 
  188.      * @param output 
  189.      */  
  190.     public static void closeOutputStream(OutputStream output){  
  191.         if(output != null){  
  192.             try {  
  193.                 output.close();  
  194.             } catch (IOException e) {  
  195.                 logger.error("关闭输出文件失败!");  
  196.                 logger.error(e);  
  197.             }  
  198.         }  
  199.     }  
  200. }  

 

说明: 下载下来的flashPaper安装程序解压后放置在 WebContent/bin/目录下。

程序自动的时候自动安装,若检测到没有使用系统还原功能,自动拷贝文件到系统system32目录下。

 

2、在上面贴出的代码中,使用FlashPaperUtil. fileToSwf()函数即可完成对可支持文档的转换。即转成swf文件。

 

3、显示转成成的swf文件。

displaySwf.jsp

 

[html] view plaincopy
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>  
  2. <%@ taglib prefix="c" uri="/WEB-INF/tld/c.tld" %>  
  3. <%  
  4.     String webRoot = request.getContextPath();   
  5. %>  
  6.   
  7. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  8. <html>  
  9.     <head>  
  10.      <base href="<%=webRoot%>/view/common/" />    
  11.         <title>在线显示文档</title>           
  12.         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />   
  13.         <style type="text/css" media="screen">  
  14.             html,body{    
  15.                 margin: 0px;  
  16.                 padding: 0px;  
  17.                 overflow: hidden;    
  18.                 height: 100%;    
  19.             }    
  20.             #content{    
  21.                 width:100%;    
  22.                 height:100%;    
  23.                 MARGIN: 0px auto;  
  24.             }    
  25.         </style>   
  26.     </head>  
  27.     <body>   
  28.         <c:if test="${swfUrl!=null}">  
  29.             <div id="content">  
  30.                 <object   
  31.                     classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"   
  32.                     codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0"  
  33.                     width="100%"  
  34.                     height="100%"  
  35.                     >  
  36.                     <param name="movie" value="${swfUrl}" />  
  37.                     <param name="quality" value="high" />  
  38.                     <param name="allowFullScreen" value="true" />  
  39.                 <embed    
  40.                     pluginspage="http://www.macromedia.com/go/getflashplayer"  
  41.                     type="application/x-shockwave-flash"   
  42.                     src="${swfUrl}"   
  43.                     allowfullscreen="true"  
  44.                     quality="high"  
  45.                     width="100%"  
  46.                     height="100%"   
  47.                     >  
  48.                 </embed>  
  49.                 </object>               
  50.             </div>  
  51.         </c:if>  
  52.         <c:if test="${swfUrl==null}">  
  53.             <div class="box error center" style="width:60%;">  
  54.                 <h1>没有指定要显示的文档路径!</h1>  
  55.             </div>  
  56.         </c:if>  
  57.    </body>   
  58. </html>   

 

处理请求的controller类中相关方法:

 

[java] view plaincopy
  1. /** 
  2.      * 显示在线文档。 
  3.      * @return 
  4.      */  
  5.     @RequestMapping("show")  
  6.     public String show(String swfUrl, HttpServletRequest request){  
  7.         request.setAttribute("swfUrl", swfUrl);  
  8.         return "common/displaySwf";  
  9.     }  


请求显示在线文档的url如下:

 

 

[html] view plaincopy
  1. 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,至此为止已经完成各种文档的转换和显示问题,希望能有同样需求的同仁们少走弯路。