这几天做项目碰到一个需求,需要实现word的在线预览功能,在网上百度了好多资料。发现很多的实现方式都是通过 openoffice + swftools + flexpaper来完成。 基本思路是先用openoffice将word转成pdf,然后再用swftools将pdf转成swf,最后通过flexpaper将swf展示在页面上。
刚开始我也是想通过这种方法来实现在线预览的功能。后面一边在网上找资料一边实现,最后到了用flexpaper将swf展示在页面的阶段,尝试了一下发现flexpaper的效果不怎么好(有卡顿,不流畅)。
于是寻思着另辟蹊径,后面有了第二种实现方案,将word转化成的pdf直接在浏览器上展示,因为现在的谷歌已经内置了pdf的展示插件,只需要要页面中引用embed标签既可。可是这样做的话会出现一个问题。pdf打开的时候默认不是铺满屏幕的,而需要用户再去点击一下自适应宽度按钮才行,而且百度了很久也没有找到应该如何控制默认缩放,所以第二种方案也被我放弃了。
最后我是通过将pdf文件在线转成图片,然后再将图片展示在页面上来解决的。当然这样做的话,效率会很低,解决方法是将word文档先进行预处理。
首先需要安装openoffice,这个东东会提供我们word转pdf的服务。这个自行在网上百度找一个4点多的版本下载就可以了,大概100多m左右。
安装完成后,需要启动openoffice的服务。
//进入安装openoffice的progra路径 cd C:\Program Files (x86)\OpenOffice 4\program //启动服务 soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
当然,如果每次开机都要去启动服务那简直就是太麻烦了,所以可以将这个服务注册为一开机就启动,由于这个服务开启的话,消耗的内存感人,所以我没有把他注册成开机启动。
word转换成pdf的代码实现:
/** * office转pdf * @param sourceFile pdf的文件目录 * @param destFile pdf输出的目标目录 * @return */ public static int office2PDF(String sourceFile, String destFile) { try { File inputFile = new File(sourceFile); if (!inputFile.exists()) { return -1;// 找不到源文件, 则返回-1 } // 如果目标路径不存在, 则新建该路径 File outputFile = new File(destFile); if (!outputFile.getParentFile().exists()) { outputFile.getParentFile().mkdirs(); } // connect to an OpenOffice.org instance running on port 8100 OpenOfficeConnection connection = new SocketOpenOfficeConnection("127.0.0.1", 8100); connection.connect(); // convert DocumentConverter converter = new OpenOfficeDocumentConverter( connection); converter.convert(inputFile, outputFile); // close the connection connection.disconnect(); System.out.println("word转pdf成功"); return 0; } catch (ConnectException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return 1; }
然后就是要处理将pdf转换成图片了。这里需要下载一个PDFRenderer.jar 的jar包
以下是PDF转图片的核心代码。
public static void changePdfToImg(String pafPath, String imgPath) { try { File file = new File(pafPath); RandomAccessFile raf = new RandomAccessFile(file, "r"); FileChannel channel = raf.getChannel(); MappedByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); PDFFile pdffile = new PDFFile(buf); for (int i = 1; i <= pdffile.getNumPages(); i++) { PDFPage page = pdffile.getPage(i); Rectangle rect = new Rectangle(0, 0, ((int) page.getBBox() .getWidth()), ((int) page.getBBox().getHeight())); int n = 6; /** 图片清晰度(n>0且n<7)【pdf放大参数】 */ Image img = page.getImage(rect.width * n, rect.height * n, rect, /** 放大pdf到n倍,创建图片。 */ null, /** null for the ImageObserver */ true, /** fill background with white */ true /** block until drawing is done */ ); BufferedImage tag = new BufferedImage(rect.width * n, rect.height * n, BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage(img, 0, 0, rect.width * n, rect.height * n, null); FileOutputStream out = new FileOutputStream(imgPath + "\\"+ i + ".jpg"); /** 输出到文件流 */ JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param2 = encoder.getDefaultJPEGEncodeParam(tag); param2.setQuality(1f, true); /** 1f~0.01f是提高生成的图片质量 */ encoder.setJPEGEncodeParam(param2); encoder.encode(tag); /** JPEG编码 */ out.close(); } channel.close(); raf.close(); unmap(buf); /** 如果要在转图片之后删除pdf,就必须要这个关闭流和清空缓冲的方法 */ System.out.println("生成图片成功"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @SuppressWarnings("unchecked") private static void unmap(final Object buffer) { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { Method getCleanerMethod = buffer.getClass().getMethod( "cleaner", new Class[0]); getCleanerMethod.setAccessible(true); sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod .invoke(buffer, new Object[0]); cleaner.clean(); } catch (Exception e) { e.printStackTrace(); } return null; } }); }
将pdf转换成图片之后,程序再去将图片读出来然后展示在网页上就可以了。