java实现在线预览功能 swftools+flexPaper

最近做项目用户有个需求,要求在线预览上传的pdf文件。遂上网寻找解决路线,一阵狂搜,得到答案swftools+flexPaper.

swftools:用来将pdf文件转换成swf文件http://www.swftools.org/download.html

flexPaper:用来在线预览swf文件http://flexpaper.devaldi.com/download/下载Download Web Server Package版本。

写了一个工具类用来调用本地应用

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116packagecom.hyges.rsac.utils;importjava.io.BufferedReader;importjava.io.File;importjava.io.InputStream;importjava.io.InputStreamReader;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;publicclassNativeApplicationInvocationHandler {publicstaticLog logger = LogFactory.getLog(NativeApplicationInvocationHandler.class);privatestaticString[] windows =newString[] {"cmd","/c"};/*** 暴露给用户的调用函数** @param workDir* 工作目录* @param command* 执行命令*/publicstaticvoidinvocate(String workDir, String... command) {if(isWinPlatform()) {// windows平台booleancmd =false;booleanc =false;// 判断命令里面是否包含cmd /cfor(String item : command) {if(item.contains("cmd")) {cmd =true;}if(item.contains("/c")) {c =true;}}if(cmd && c) {invocateForInner(workDir, command);}else{String[] newCommand =newString[command.length + windows.length];System.arraycopy(windows,0, newCommand,0, windows.length);System.arraycopy(command,0, newCommand, windows.length, command.length);invocateForInner(workDir, newCommand);}}else{// linux平台invocateForInner(workDir, command);}}/*** 判断宿主平台** @return*/privatestaticbooleanisWinPlatform() {String platform = System.getProperty("os.name");logger.info("本地应用调用:宿主平台是"+ platform);returnplatform.toLowerCase().indexOf("windows") > -1?true:false;}/*** 记录调用错误** @param process* @throws IOException*//** private static void loggingError(Process process) throws IOException {* BufferedInputStream bis = new* BufferedInputStream(process.getErrorStream()); int tmp; ArrayList<Byte>* list = new ArrayList<Byte>(); while ((tmp = bis.read()) != -1) {* list.add((byte) tmp); } Object[] tmpA = list.toArray(); byte[] result =* new byte[tmpA.length]; for (int i = 0; i < tmpA.length; i++) { result[i]* = (Byte) tmpA[i]; } bis.close(); logger.error("本地应用调用:调用出现错误:" + new* String(result, Charset.defaultCharset())); }*//*** 类内部的调用函数** @param workDir* @param command*/privatestaticvoidinvocateForInner(String workDir, String... command) {Process process;ProcessBuilder pb;pb =newProcessBuilder(command);pb.directory(newFile(workDir));pb.redirectErrorStream(true);// 合并stdout和stderrtry{logger.info("本地应用调用:调用开始");process = pb.start();InputStream is = process.getInputStream();BufferedReader br =newBufferedReader(newInputStreamReader(is));StringBuilder sb =newStringBuilder();String line;// 清空process.getInputStream()的缓冲区,以免造成程序阻塞。while((line = br.readLine()) !=null) {sb.append(line);}br.close();if(process.waitFor() !=0|| process.exitValue() !=0) {logger.error("本地应用调用:调用出现错误:"+ sb.toString());}else{process.destroy();logger.info("本地应用调用:调用成功结束");}}catch(Exception e) {logger.error("程序调用出现错误", e);}}}

在写这个工具类时遇到了两个问题:

第一个问题,在转换大的pdf文件时,运行很慢不能成功转换。上网查了一下原因,有的说是Process类里面I/O流产生阻塞,导致线程不能继续执行,遂查看api

By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods,, and. The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

大致意思,默认情况下被创建的子进程没有终端或控制台。所有的标准I/O流都被重定向到了父线程,可以通过,和.方法获得这些流。父进程通过这些流与子进程交互。有一些宿主平台只提供了大小有限制的缓存,来缓存这些输入输出流。当缓冲区填满了,就不能及时写入输入流或读出子进程的输出流,这可能导致子进程阻塞,甚至死锁。

原因找到了,就是因为程序在被调用执行时,产生了大量的输出流,而笔者又没有及时读取子进程的输出,所以导致子进程被阻塞了。(以上工具类已经读取了子进程的输出流)

这里要解释一下和.的区别

以下属于errorStream

一下属于inputStream

这下读者该能够区分什么时候调用哪个方法了吧。

第二个问题:

用flexPaper查看被转换的swf文件时,右上角总是有个小圆圈再转,并且显示已经100%了,但就是打不开。问题是flash版本问题在调用pdf2swf.exe时加上版本信息就好了

12invocate("D:\\Program Files (x86)\\SWFTools","cmd","/c","pdf2swf.exe","-t","d:\\hibernate_reference.pdf","-s","flashversion=9","-o","d:\\hibernate_reference.swf");

这样问题顺利解决。

以下是显示页面主要代码

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647<script type="text/javascript"src="resources/component/flexPaper/js/flexpaper.js"></script><script type="text/javascript"src="resources/component/flexPaper/js/flexpaper_handlers.js"></script><divclass="wrap mt20"><divclass="website">当前位置:<a href="/">首页</a> > <a href="publication/list">协会刊物</a>>${name }</div><divclass="periodical-cont"><input name="swfPath"value="${path}"hidden="true"id="swfPath"/><div id="documentViewer"class="flexpaper_viewer"style="width: 770px; height: 500px"></div><script type="text/javascript">var startDocument ="Paper";var swfPath = $("#swfPath").val();$('#documentViewer').FlexPaperViewer({config : {SWFFile : swfPath,Scale :0.6,ZoomTransition :'easeOut',ZoomTime :0.5,ZoomInterval :0.2,FitPageOnLoad :true,FitWidthOnLoad :false,FullScreenAsMaxWindow :false,ProgressiveLoading :false,MinZoomSize :0.2,MaxZoomSize :5,SearchMatchAll :false,InitViewMode :'Portrait',RenderingOrder :'flash',StartAtPage :'',ViewModeToolsVisible :true,ZoomToolsVisible :true,NavToolsVisible :true,CursorToolsVisible :true,SearchToolsVisible :true,WMode :'window',localeChain :'zh_CN'}});</script></div>

我们一直在旅行,一直在等待某个人可以成为我们旅途的伴侣,

java实现在线预览功能 swftools+flexPaper

相关文章:

你感兴趣的文章:

标签云: