Java实现仿百度文库文档在线阅读

为了实现这个功能,我们需要用到如下软件,Java+FlexPaper+SwfTool+OpenOffice这四大件.

1、思路

我们将doc、ppt等文档格式通过openoffice转换成pdf的格式,然后用SWFTool工具将pdf切分成小块的swf文件或者大型的swf文件或者图片格式也行.一般都采用小块swf或者小块图片格式,这样用户就能按需加载.比如我们的pdf文件有80M,用户打开预览页面加载的就是当前查看页的前一页、当前页、后一页,当然这数字是可以通过调整配置去设置.所以用户可以很快的去打开页面进行预览而不是加载一个整体的文件.

2、环境的安装

1.安装OpenOffice,官网下载地址:下载地址,我是使用的最新版.具体安装方法自行百度.

2.启动OpenOffice服务,CMD命令进入OpenOffice安装目录下的program目录,键入如下命令

/opt/openoffice4/program/soffice “-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager” -nologo -headless -nofirststartwizard &

这个是启动office后台进行转换的一个服务,无图形界面.

3.下载JODConverter:下载地址,项目中主要使用lib目录下的jar包。

4.下载并安装SWFTools:下载地址,下载exe文件安装完成即可

5.下载FlexPlayer

下载地址

未使用最新版,使用1.5.1

6.下载相关的xpdf及字符集(处理中文文档字体的错误)

xpdf-3.02pl5-win32.zip 
下载地址为 
ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.02pl5-win32.zip 
xpdf-chinese-simplified.tar.gz 
下载地址为 
ftp://ftp.foolabs.com/pub/xpdf/xpdf-chinese-simplified.tar.gz 
也可以去http://www.foolabs.com/xpdf/download.html查找你自己需要的字符集

您也可以去官网下载最新版本

1.解压xpdf-3.02pl5-win32.zip,解压后修改名称为xpdf,并将其考到c盘根目录下【路径可以随意指定,但是执行pdf2swf指令时要指定到当前目录】。 
2.解压xpdf-chinese-simplified,将xpdf-chinese-simplified放置xpf目录下 
3.修改xpdf-chinese-simplified目录下的add-to-xpdfrc文件

Add-to-xpdfrc代码


  1. #----- begin Chinese Simplified support package (2004-jul-27)
  2. cidToUnicode Adobe-GB1 /usr/local/share/xpdf/chinese-simplified/Adobe-GB1.cidToUnicode
  3. unicodeMap ISO-2022-CN /usr/local/share/xpdf/chinese-simplified/ISO-2022-CN.unicodeMap
  4. unicodeMap EUC-CN /usr/local/share/xpdf/chinese-simplified/EUC-CN.unicodeMap
  5. unicodeMap GBK /usr/local/share/xpdf/chinese-simplified/GBK.unicodeMap
  6. cMapDir Adobe-GB1 /usr/local/share/xpdf/chinese-simplified/CMap
  7. toUnicodeDir /usr/local/share/xpdf/chinese-simplified/CMap
  8. fontDir C:\WINDOWS\Fonts
  9. #添加字体格式
  10. displayCIDFontTT Adobe-GB1 /usr/local/share/xpdf/chinese-simplified/Fonts/simhei.ttf
  11. #displayCIDFontTT Adobe-GB1 /usr/..../gkai00mp.ttf
  12. #----- end Chinese Simplified support package

如果您未注释掉下面提供的类中的languagedir段,则会在转换的时候显示如下信息 
表示成功添加了中文字体 

3.开发过程

1.添加JODConverter的jar包,同时也需要将所依赖的包添加进工程.

2.咱们需要一个转换的类


  1. public class Converter2Swf {
  2. private File pdfFile;
  3. private File swfFile;
  4. private File docFile;
  5. private File originalFile;
  6. private static final String[] extArray = {"doc","docx","ppt","pptx","xls","xlsx","txt","rtf"};
  7. public Converter2Swf(String fileString) {
  8. init(fileString);
  9. }
  10. /*
  11. * 重新设置 file @param fileString
  12. */
  13. public void setFile(String fileString) {
  14. init(fileString);
  15. }
  16. /*
  17. * 初始化 @param fileString
  18. */
  19. private void init(String fileString) {
  20. originalFile = new File(fileString);
  21. String fileName = FilenameUtils.getBaseName(fileString);
  22. String fileExt = FilenameUtils.getExtension(fileString);
  23. if (Converter2Swf.can2Pdf(fileExt)) {
  24. docFile = new File(fileString);
  25. pdfFile = new File(fileName + ".pdf");
  26. swfFile = new File(fileName+new Date().getTime() + ".swf");
  27. } else if ("pdf".equals(fileExt)) {
  28. pdfFile = new File(fileString);
  29. swfFile = new File(fileName+new Date().getTime() + ".swf");
  30. }
  31. }
  32. public static boolean can2Pdf(String ext) {
  33. for (String temp : extArray) {
  34. if(temp.equals(ext))
  35. return true;
  36. }
  37. return false;
  38. }
  39. public static boolean can2Swf(String ext) {
  40. if("pdf".equals(ext))
  41. return true;
  42. for (String temp : extArray) {
  43. if(temp.equals(ext))
  44. return true;
  45. }
  46. return false;
  47. }
  48. /*
  49. * 转为PDF @param file
  50. */
  51. private void doc2pdf() throws Exception {
  52. OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
  53. connection.connect();
  54. DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
  55. converter.convert(docFile, pdfFile);
  56. connection.disconnect();
  57. }
  58. /*
  59. * 转换成swf
  60. */
  61. private int pdf2swf() throws Exception {
  62. int countFile = -1;
  63. int errorFlag = 0;
  64. String path = File.separator+FilenameUtils.getPath(swfFile.getPath());
  65. String filename = FilenameUtils.getBaseName(swfFile.getPath()) + "%." + FilenameUtils.getExtension(swfFile.getPath());
  66. String[] command = {"pdf2swf", pdfFile.getPath(), "-o", path + filename, "-T 9","-s","languagedir=/usr/local/share/xpdf/chinese-simplified"};
  67. ProcessBuilder proc = new ProcessBuilder(command);
  68. proc.redirectErrorStream(true);
  69. Process p = proc.start();
  70. String outlog = loadStream(p.getInputStream());
  71. if(StringUtils.contains(outlog,"FATAL"))
  72. errorFlag = 2;
  73. else if(StringUtils.contains(outlog,"ERROR"))
  74. errorFlag = 1;
  75. if(errorFlag == 1)
  76. System.err.println(outlog);
  77. else if (errorFlag == 2) {
  78. System.err.println(outlog);
  79. countFile = 0;
  80. } else {
  81. System.out.println(outlog);
  82. countFile = StringUtils.countMatches(outlog, FilenameUtils.getBaseName(pdfFile.getName()));
  83. }
  84. if (pdfFile.exists() && !pdfFile.getPath().equals(originalFile.getPath())) {
  85. pdfFile.delete();
  86. }
  87. return countFile;
  88. }
  89. static String loadStream(InputStream in) throws IOException {
  90. int ptr = 0;
  91. BufferedReader reader = new BufferedReader(new InputStreamReader(in));
  92. StringBuilder buffer = new StringBuilder();
  93. while ((ptr = reader.read()) != -1) {
  94. buffer.append((char) ptr);
  95. }
  96. return buffer.toString();
  97. }
  98. /*
  99. * 转换主方法
  100. */
  101. public int conver() throws Exception {
  102. int countFile = -1;
  103. if (swfFile != null) {
  104. if (docFile != null && can2Pdf(FilenameUtils.getExtension(docFile.getPath())))
  105. doc2pdf();
  106. if(pdfFile != null && can2Swf(FilenameUtils.getExtension(pdfFile.getPath())))
  107. countFile = pdf2swf();
  108. }
  109. return countFile;
  110. }
  111. /*
  112. * 返回文件路径 @param s
  113. */
  114. public String getswfPath() {
  115. if (swfFile.exists()) {
  116. String tempString = swfFile.getPath();
  117. tempString = tempString.replaceAll("\\\\", "/");
  118. return tempString;
  119. } else {
  120. return "";
  121. }
  122. }
  123. /*
  124. * 设置输出路径
  125. */
  126. public void setOutputPath(String outputPath) {
  127. File output = new File(outputPath);
  128. if(!output.exists())
  129. output.mkdirs();
  130. if (!outputPath.equals("")) {
  131. if (outputPath.charAt(outputPath.length() - 1) == '/') {
  132. swfFile = new File(outputPath + FilenameUtils.getBaseName(swfFile.getPath()) + ".swf");
  133. } else {
  134. swfFile = new File(outputPath + File.separator + FilenameUtils.getBaseName(swfFile.getPath()) + ".swf");
  135. }
  136. }
  137. }
  138. public File getSwfFile() {
  139. return swfFile;
  140. }
  141. public static void main(String s[]) {
  142. File file = new File("/home/michael/06142722_m3Sr.pdf");
  143. Converter2Swf d = new Converter2Swf(file.getPath());
  144. d.setOutputPath(RequestContext.root());
  145. int swfcount = 0;
  146. try {
  147. swfcount = d.conver();
  148. } catch (Exception e) {
  149. e.printStackTrace();
  150. }
  151. }
  152. }

该类只是单独对文件进行转换成pdf swf,可以在用户上传的时候进行对文件的处理,也可以在用户上传完之后通过一定定时任务去处理,这样用户就不需要为了等待服务器的转换而浪费时间.该代码是建立在linux基础上进行,如果您是要在window上进行处理则要稍稍修改代码 
该代码这里进行切分是按页切分成小型的swf文件 
如果不需要则command中的-T 9则行 
该代码引入了中文字体库,否则在进行转换成swf的时候可能会出现一些缺少中文字体等错误,如果您不需要处理这种中文的错误,您也可以在command中去掉


  1. languagedir=/usr/local/share/xpdf/chinese-simplified

通过执行这个类的main方法可以测试是否成功生成swf文件 
3.如果您已经成功产生了如上的swf文件,则可以进行最后一步,在页面上调用FlexPaperViewer的swf文件显示就可以


  1. type="text/javascript">
  2. var fp = new FlexPaperViewer(
  3. '/js/flexpaper/FlexPaperViewer',
  4. 'viewerPlaceHolder', { config : {
  5. SwfFile : '{$doc.swfurl(),$doc.swfcount()}',
  6. Scale : 0.6,
  7. ZoomTransition : 'easeOut',
  8. ZoomTime : 0.5,
  9. ZoomInterval : 0.2,
  10. FitPageOnLoad : false,
  11. FitWidthOnLoad : true,
  12. FullScreenAsMaxWindow : false,
  13. ProgressiveLoading : true,
  14. MinZoomSize : 0.2,
  15. MaxZoomSize : 5,
  16. SearchMatchAll : false,
  17. InitViewMode : 'Portrait',
  18. ViewModeToolsVisible : true,
  19. ZoomToolsVisible : true,
  20. NavToolsVisible : true,
  21. CursorToolsVisible : true,
  22. SearchToolsVisible : true,
  23. localeChain: 'zh_CN'
  24. }});

这部分代码不同版本的flexpaper会稍有不同,具体细节参考官网的文档说明,如果您用的最新版的flexpaper,可能这样的配置或者调用方式有些不同.

$doc.swfurl()是代码的swf的url地址,而后面的$doc.swfcount()代表该文件转换成功生成的swf小文件个数. 
需要注意的是我们的这个swfurl()方法返回的链接是必须不能带有空格之类的,所以我们在转换生成swf文件的时候最好采用时间来作为文件命名的一个参照,这样就能避免出现空格的问题,同时对于大规模的部署这个应用,我们还得处理在Linux上,一个目录下文件不能超过10000个文件,所以我们可以分成大大小小的目录去处理.

最后的效果可以参考

效果演示

如果遇到什么问题,可以直接评论,我将竭尽所能帮助你.

http://www.blinkcoder.com/read-the-document-implemented-in-java-imitation-online

你可能感兴趣的:(Java)