能够以 pdf 格式下载数据是您在构建 Web 应用程序时会遇到的常见要求。在 Rails 中有不同的方法可以实现这一点。我们将研究用于生成 pdf 文档的两种主要方法:使用 Ruby 使用 DSL 定义和样式化文档,或者使用将 HTML 转换为 PDF 的库。
今天我们将重点介绍三种流行的宝石:
-
大虾(使用 DSL 方法)
-
PDFKit(使用生成器)
-
邪恶的 PDF(也使用生成器)。
HTML 到 PDF 或 Ruby 生成?
这个问题的答案通常取决于偏好和项目要求。HTML 到 PDF 可以更快,特别是如果您已经有一个视图来显示您想要在 PDF 中显示的内容。在这种情况下,您不必编写更多代码来生成 PDF 文件。但是,这种方法会使控制文档的布局变得更加困难,尤其是在处理多页文档时。内容往往会被截断并在页面之间拆分。确实,通过一些 CSS 样式,您可以对分页符进行一些控制。但是,对于跨越多个页面并包含可变长度内容、页眉和页脚的更复杂的 PDF 文档,将难以控制每个页面的呈现方式。在这些情况下,使用 Prawn 可能更有意义。
使用像 Prawn 这样的库,您必须使用 Prawn 的 DSL 自己完成所有内容样式和定位。这里的优点是可以更好地控制事物的显示方式和页面中断的位置。
我们将为如下所示的网页生成一个 PDF 文件,其中包含一些静态文本、一张图像和一些数据库记录的表格。
虾
要使用 Prawn,请将 gem 包含在 Gemfile 中并运行bundle install
gem 'prawn'
在文件中注册 PDF mime 类型config/initializers/mime_types.rb
。
Mime::Type.register "application/pdf", :pdf
现在我们需要设置控制器动作来响应对 PDF 格式的请求。
对于我的 Products 控制器,我有一个index
要修改的操作,如图所示。
class ProductsController < ApplicationController
def index
@products = Product.all
respond_to do |format|
format.html
format.pdf do
pdf = Prawn::Document.new
send_data pdf.render, filename: 'report.pdf', type: 'application/pdf'
end
end
end
end
当.pdf
附加到特定 url 的末尾时,上面将生成一个没有内容的 PDF 文件。就我而言http://localhost:3000/products.pdf。
为了从控制器中分离出 pdf 生成代码,我创建了一个app/pdfs
目录并在文件中添加了一个新类app/pdfs/report_pdf.rb
。
我更改了控制器代码以使用新类。
class ProductsController < ApplicationController
def index
@products = Product.all
respond_to do |format|
format.html
format.pdf do
pdf = ReportPdf.new(@products)
send_data pdf.render, filename: 'report.pdf', type: 'application/pdf'
end
end
end
end
下面的代码显示了如何生成上面显示的网页的 PDF。我已经评论它以显示我在做什么。
class ReportPdf < Prawn::Document
def initi