`

用 Ruby on Rails 实现适应各种平台的在线 Office 文档预览

阅读更多
前言

在许多Web应用中都需要预览文档的功能。而用户可能用不同的设备访问Web应用,可能是装有Windows系统的PC台式机,也有可能是iOS系统的iPad。一般来说,要预览的文档通常是主流的Office文档,包括.doc、.ppt、.docx、.pptx文档,也包括Adobe的.pdf文档。

因此开发一个能够在不同客户端上使用的,支持主流Office文档类型的在线文档预览系统就显得非常重要。

目标

实现基于Web的跨平台的在线预览功能,支持主流Office文档。另外我们的服务器是Linux系统,不能够安装Microsoft Office软件。

我的解决方案

先大致地说一下我是如何实现的。为了实现这个功能,我用了下面的组件:

PDF.js
OpenOffice
PyODConverter
PDF.js 是Mozilla实验室开发的关于HTML5技术的一个开源项目,用于在网页上显示PDF文档,而不需要任何浏览器插件等原生代码。目前这个开源项目放在了GitHub上,网址是https://github.com/andreasgal/pdf.js

演示地址:http://mozilla.github.io/pdf.js/web/viewer.html

OpenOffice是Apache开源软件基金会开发的一款开源软件,是可以在Linux上运行的Office软件。OpenOffice可以打开主流的Microsoft Office的各种文档,例如.doc,.docx,.ppt,.pptx格式的文档。OpenOffice有一个文档转换服务,这个服务是以网络服务的形式运行的。启动这个服务,我就可以在任何类型的代码中通过端口调用这个服务。

PyODConverter是一个Python脚本,用于自动化的文档格式转换,依赖于LibreOffice or OpenOffice。我用它把Office文档转成PDF文档。

PyODConverter代码托管在 https://github.com/jamayka/barberry-plugin-openoffice/tree/master/externals/pyodconverter 上。

实现过程

整个实现分为**“Office文档转PDF”**和**“PDF文档在Web端显示”**两部分。
,后端负责将各种Office文档通过OpenOffice服务转换成PDF文档,而前端通过pdf.js显示PDF的内容。由于是采用了pdf.js显示PDF文档,浏览器端不需要安装任何插件,但是需要支持部分HTML5的功能特性。因此旧浏览器例如IE8,IE7,IE6就不能够使用pdf.js了.

Office文档转PDF

我利用了OpenOffice服务将各种Office文档转换成了PDF文档。写的脚本是*rake task*脚本,这样我可以用*rake*命令运行此脚本。这个脚本作为一个守护进程运行,它不断地检查系统里是否有新的上传文件。如果有新上传的文件,则启动转换过程,步骤如下:

启动OpenOffice的服务
检查是否有新的Office文档上传
调用PyODConverter转换文档
更新Model上的字段,指向生成的用于预览的PDF
重复步骤2到4
整个rake task脚本的代码如下:

# -*- encoding : utf-8 -*-
    PYTHON_PATH = '/opt/openoffice4/program/python'
    CONVERTER_PATH = File.expand_path('../DocumentConverter.py', __FILE__)

    def gen_preview(beDaemon = false)
      begin
        no_preview_materials = CoursewareMaterial.where(preview_file_name: nil).where(['doc', 'docx', 'ppt', 'pptx'].map {|x| "upload_file_name LIKE '%.#{x}'"}.join(' or '))
        if no_preview_materials.size > 0
          puts "Prepare to process #{no_preview_materials.size} items."
          no_preview_materials.each do |material|
            begin
              generate_preview material
            rescue
              puts "[Exception] #{$!}".red
            end
          end
        end

        break if not beDaemon

        sleep 30
      end while true
    end


    def generate_preview material
      puts "Generating preview PDF for [#{material.upload_file_name}]..."
      if material.upload.path.to_s =~ /\.(doc|docx|ppt|pptx|pdf)$/
        tmpPdfPath = File.join(Dir.tmpdir, File.basename(material.upload.path, '.*') + '.pdf')

        # try to delete existing temporary file if it exists.
        begin
          File.delete tmpPdfPath
        rescue
          # do nothing
        end

        # relaunch openoffice if it quit.
        if `pgrep soffice`.size == 0
          puts 'Relaunch OpenOffice service.'
          spawn 'soffice "-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" -norestore -nofirststartwizard -nologo -headless &'
        end

        out = nil
        cmd = "#{PYTHON_PATH} #{CONVERTER_PATH} '#{material.upload.path}' '#{tmpPdfPath}'"
        puts "Execute command: \n#{cmd}"
        out = `#{cmd}`
        if File.exists?(tmpPdfPath)
          material.preview = File.open(tmpPdfPath, 'rb')
          material.save
          File.delete tmpPdfPath
          puts "Preview PDF for [#{material.upload_file_name}] is generated.".green
        else
          puts "An error occured when invoke DocumentConverter.py. #{out}".red
        end
      else
        puts "The material [#{material.upload_file_name}] is not available for generating preview PDF.".yellow
      end
    end
PDF文档在Web端显示

首先在asset pipeline中添加pdf.js,这一步可以通过引入*pdfjs-rails*这个Gem实现。然后在页面中引用需要的js和css资源即可,而这些资源包含在*pdfjs-rails*中。

Gem pdfjs-rails代码托管在https://github.com/concordia-publishing-house/pdfjs-rails中。

然后在view上添加前端代码。我用的是ERB,因此对应的文件是preview.html.erb。此文件中的代码如下所示:

    <%= javascript_include_tag "compatibility" %>
    <%= javascript_include_tag "l10n" %>
    <%= javascript_include_tag "pdf" %>
    <%= javascript_include_tag "pdfviewer" %>
    <%= stylesheet_link_tag"viewer", :media => "all" %>
    ......
    <div>
        <%  if not (pdf_url.nil? or pdf_url.empty?) %>
            <b>内容预览:</b>
            <%=   pdf_viewer pdf_url %>
        <%  end %>
    </div>
    ......
如以上代码所示,*pdfjs_rails*提供了用于自动生成HTML的*pdf_viewer*方法,简化了代码。当要显示一个文档时,还需要判断这个文档对应的PDF文档有没有生成,因此需要一个类似于if pdf_url.nil?的代码。为了简单起见,我就直接把此代码写在view上了。

安装部署

安装OpenOffice到Linux CentOS

这里有详细说明 http://www.if-not-true-then-false.com/2010/install-openoffice-org-on-fedora-centos-red-hat-rhel/

以作为后台服务的方式运行OpenOffice

这里有详细说明 http://stackoverflow.com/questions/11591643/failed-to-connect-to-openoffice-headless-mode

下载PyODConverter脚本

从 https://github.com/concordia-publishing-house/pdfjs-rails 下载PyODConverter脚本,放在lib/tasks/prevew目录下面,然后我把它直接上传到我的代码库里。

演示

其它几种方案

我在方案选型的过程中研究了好几种方案,但是除了上面所描述的方案之外的其他所有方案都因为各种原因而不能满足要求。下面一一列举这些未选中的方案,以及解释为何它们满足不了要求。

FlexPaper

FlexPaper 是一个商业软件,但是有采用GPLv3开源协议的免费版。然而,它仅支持ASP.NET、PHP和Java,而且部署相对复杂。我的系统是基于Linux的,开发技术是Ruby on Rails,因此不太容易和它整合在一起。

Accusoft Document Viewers

Accusoft Document Viewers 是一个商业软件,有一些很酷的Demos,下面列举两个Demo的网址。

http://prizmdemos.accusoft.com/flash.php
http://prizmdemos.accusoft.com/html5.php
可是这个软件的价格太高,而且不是提供一个组件,而是提供一套解决方案,对于我们的目标来说,这些解决方案太“重”了。

Google的文档预览服务

Google的文档预览服务(Google Docs Viewer) 真心很不错,这里有个应用实例,但是最大的问题是经常被墙,无法稳定地工作。

CUPS-PDF

根据一个StackOverflow上的解答,有一个叫CUPS-PDF的软件可以安装在Linux系列(包括Mac OS X)的操作系统上。该软件能够为系统添加一个PDF打印机。它是另一种文档转PDF的方法,通过安装PDF打印机将文档“打印”成PDF文档。用OpenOffice的命令行工具可以打印一个文档,并指定要使用的打印机。只要指定使用CUPS-PDF的打印机,就能够输出一个PDF文件到文件系统中的一个位置上。

这种方法可以很精确地将文档转换成PDF文档,可以说是“所打印即所得”

原文:
分享到:
评论

相关推荐

    Ruby on Rails Tutorial

    《Ruby on Rails Tutorial》中文版(原书第2版,涵盖 Rails 4) Ruby 是一门很美的计算机语言,其设计原则就是“让编程人员快乐”。David Heinemeier Hansson 就是看重了这一点,才在开发 Rails 框架时选择了 Ruby...

    ruby on rails 101

    引用自Nathan Torkington的话:“使用Ruby on Rails就像观看功夫电影一样,看似弱小的新手框架却能够用各种创造性的方式打败众多强大的对手。”这句话生动地描述了Ruby on Rails的独特之处以及它在Web开发领域的影响...

    Ruby on Rails安装包全集(Linux)

    Ruby on Rails是一款基于Ruby语言的开源Web开发框架,它遵循MVC(模型-视图-控制器)架构模式,简化了Web应用的开发流程。在Linux环境下安装Ruby on Rails需要一系列的依赖包和步骤,本资源包提供了所需的所有组件,...

    ruby on rails最新版

    Ruby on Rails,简称Rails,是基于Ruby编程语言的一个开源Web应用程序框架,它遵循MVC(模型-视图-控制器)架构模式,旨在提高开发效率和代码的可读性。Rails以其“约定优于配置”(Convention over Configuration)...

    ruby on rails社区网站开发源码

    Ruby on Rails,简称Rails,是由David Heinemeier Hansson创建的一个开源Web应用程序框架,它基于Ruby编程语言。这个框架以其MVC(Model-View-Controller)架构、约定优于配置(Convention over Configuration)的...

    ruby on rails在线考试系统

    Ruby on Rails(简称Rails)是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构...这个系统需要综合运用Ruby on Rails的各种特性和最佳实践,以提供稳定、高效、易用的在线考试服务。

    Ruby on Rails入门经典代码

    Ruby on Rails,简称Rails,是基于Ruby语言的一个开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在使Web开发过程更加高效、简洁。本压缩包中的"Ruby on Rails入门经典代码"提供了新手学习...

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    ### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...

    ruby on rails 3 tutorial.pdf

    《Ruby on Rails 3 Tutorial》是一本专门为初学者设计的指南,旨在帮助读者快速掌握Ruby on Rails这一强大的Web开发框架。Ruby on Rails(简称Rails)是基于Ruby语言的一个开源框架,它采用MVC(Model-View-...

    ruby on rails(开发文档)

    Ruby on Rails,简称Rails,是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,极大地简化了Web应用的开发过程。Rails的哲学是“约定优于配置”,鼓励开发者遵循一套标准的...

    ruby on rails for dummies

    《Ruby on Rails for Dummies》这本书将引导读者从安装Ruby和Rails环境开始,逐步学习如何创建模型、视图和控制器(MVC架构),搭建数据库,使用路由系统,以及实现CRUD(Create, Read, Update, Delete)操作。...

    Ruby on Rails实践

    Ruby on Rails,简称Rails,是由David Heinemeier Hansson基于Ruby语言开发的一个开源Web应用程序框架。这个框架遵循“约定优于配置”(Convention over Configuration)的原则,致力于简化Web应用的开发流程,提高...

    Ruby on Rails入门权威经典

    《Ruby on Rails入门权威经典》是一本专门为初学者设计的指南,旨在帮助读者全面掌握Ruby on Rails这一强大的Web开发框架。Ruby on Rails(简称Rails)是基于Ruby编程语言的开源框架,以其“DRY(Don't Repeat ...

    ruby on rails api

    Ruby on Rails(简称Rails)是一种基于Ruby编程语言的开源Web应用程序框架,专为敏捷开发而设计,强调简洁的代码和“约定优于配置”的原则。它主要用于构建数据驱动的Web应用,借助于MVC(Model-View-Controller)...

    Ruby on Rails中文指南

    Ruby on Rails,简称Rails,是一款基于Ruby语言的开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,旨在提升开发效率和代码的可读性。Rails以其“约定优于配置”的设计理念,以及“DRY(Don't Repeat ...

    Ruby On Rails中文教材(PDF)

    本中文教材《Ruby On Rails》可能是针对初学者和有一定编程基础的开发者设计的,通过PDF格式提供,便于读者在线阅读或离线保存。PDF文档通常包含详细的教程、实例代码和可能的练习题,旨在帮助学习者全面了解和掌握...

    ruby on rails最佳敏捷开发

    Ruby on Rails,简称Rails,是一种基于Ruby语言的开源Web应用框架,它遵循敏捷开发原则,致力于简化Web开发过程。Rails的核心理念是“Convention over Configuration”(约定优于配置),这意味着开发者可以减少大量...

    ruby on rails 教程源码

    Ruby on Rails,简称Rails,是基于Ruby语言的开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,旨在使开发过程更加简洁高效。这个“ruby on rails 教程源码”很可能是为了辅助学习者深入理解Rails的...

    提升Ruby on Rails性能的几个解决方案

    Ruby On Rails 框架自它提出之日起就受到广泛关注,在“不要重复自己”,“约定优于配置”等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率。 ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate 即可...

Global site tag (gtag.js) - Google Analytics