无法使用 PDFtk 生成正确的 PDF 文件
Posted
技术标签:
【中文标题】无法使用 PDFtk 生成正确的 PDF 文件【英文标题】:Can't generate proper PDF files with PDFtk 【发布时间】:2013-07-03 17:54:21 【问题描述】:我正在使用 Ruby on Rails 3 开发一个 Web 应用程序。该应用程序的功能之一是使用 mysql 数据库中的数据来填写在 Adobe LiveCycle Designer 中设计的 PDF 模板表单。
我正在使用使用数据生成 XFDF 文件的技术,并使用它来填充实际的 PDF 文件。我正在使用 PDFtk 执行此操作,如果我从命令提示符(Windows 7 64 位)运行它,它可以正常工作。
我使用 Greg Lappen 在 http://bleep.lapcominc.com/2012/02/07/filling-pdf-forms-with-ruby-and-pdftk/ 的代码在我的 Rails 应用程序中实现了这个过程,但它似乎不起作用
输出的 PDF 无法在 Acrobat 中打开,因为它指出文件已损坏。如果我使用普通文本编辑器打开它,它所包含的只是#<StringIO:0x5958f30>
,每次输出后十六进制值都会发生变化。
生成 XML 数据的代码是正确的。我能够将它保存到一个文件中并自己通过命令提示符运行它。
def self.generate_xfdf(fields, filename)
xml = Builder::XmlMarkup.new
xml.instruct!
xml.xfdf("xmlns" => "http://ns.adobe.com/xfdf/", "xml:space" => "preserve")
xml.f :href => filename
xml.fields
fields.each do |field, value|
xml.field(:name => field)
if value.is_a? Array
value.each |item| xml.value(item.to_s)
else
xml.value(value.to_s)
end
end
xml.target!
end
我怀疑真正的问题出在下面的两个代码 sn-ps 中。我刚开始学习 Ruby on Rails,但无法调试它。我尝试了各种不同的方法,但到目前为止都没有成功。非常感谢任何帮助。
def self.stamp(input_pdf, fields)
stdin, stdout, stderr = Open3.popen3("pdftk #input_pdf fill_form - output - flatten")
stdin << generate_xfdf(fields, File.basename(input_pdf))
stdin.close
yield stdout
stdout.close
stderr.close
end
PdfStamper.stamp('C:/clean-it-template.pdf', 'LastName' => "Test Last Name", 'FirstName' => "Test First Name" ) do |pdf_io|
pdf_content = StringIO.new
pdf_content << pdf_io.read
send_data pdf_content.string, :filename=>'output.pdf', :disposition=>'inline', :type=>'application/pdf'
end
这是我的控制器类中的完整代码
require 'pdf_stamper'
class FormPagesController < ApplicationController
def pdftest
PdfStamper.stamp('C:/clean-it-template.pdf', 'LastName' => "Test Last Name", 'FirstName' => "Test First Name" ) do |pdf_io|
pdf_content = StringIO.new
pdf_content << pdf_io.read
send_data pdf_content.string, :filename=>'output.pdf', :disposition=>'inline', :type=>'application/pdf'
end
end
end
这是我正在使用的 pdf_stamper 类的完整代码
require 'builder'
require 'open3'
class PdfStamper
def self.stamp(input_pdf, fields)
stdin, stdout, stderr = Open3.popen3("pdftk #input_pdf fill_form - output - flatten")
stdin << generate_xfdf(fields, File.basename(input_pdf))
stdin.close
yield stdout
stdout.close
stderr.close
end
def self.generate_xfdf(fields, filename)
xml = Builder::XmlMarkup.new
xml.instruct!
xml.xfdf("xmlns" => "http://ns.adobe.com/xfdf/", "xml:space" => "preserve")
xml.f :href => filename
xml.fields
fields.each do |field, value|
xml.field(:name => field)
if value.is_a? Array
value.each |item| xml.value(item.to_s)
else
xml.value(value.to_s)
end
end
xml.target!
#file = File.new("C:/debug.xml", "w+")
#file.write(xml_data)
#file.close
end
end
更新 #1:
我在 Ubuntu 上运行了 Web 应用程序,但仍然遇到相同的错误。在网上搜索后,我将控制器中的代码更改为:
def pdftest
PdfStamper.stamp('/home/nikolaos/clean-it-template.pdf', 'LastName' => "Test Last Name", 'FirstName' => "Test First Name" ) do |pdf_io|
pdf_content = StringIO.new("", 'wb')
pdf_content << pdf_io.read
send_data pdf_content.string, :filename=>'output.pdf', :disposition=>'inline', :type=>'application/pdf'
end
end
我将 StringIO 更改为二进制写入模式,它可以在 Ubuntu 中运行! PDF 正确打开并填写了所有字段。我使用 Acrobat 在 Windows 上打开了相同的文件,没有问题,但是如果我在 Windows 上运行 Web 应用程序,它仍然会生成损坏的 PDF 文件。
有没有人有关于如何在 Windows 中使用它的任何解决方案?我猜这与 Windows 和 Linux 解释换行符或类似的方式有关?
【问题讨论】:
我更新了我的问题。请参阅我帖子末尾的更新 #1。 【参考方案1】:在通过 Ruby 文档进行更多搜索后,我设法解决了我的问题。现在我的应用程序能够在 Windows 上生成有效的 PDF 文件。这是我为遇到同样问题的人提供的解决方案。
解决方案是在控制器中使用 IO 代替 StringIO。
我的 FormPages 控制器代码
require 'pdf_stamper'
class FormPagesController < ApplicationController
def pdftest
PdfStamper.stamp('C:/clean-it-template.pdf', 'LastName' => "Bukas", 'FirstName' => "Nikolaos" ) do |pdf_io|
pdf_content = IO.new(pdf_io.to_i, "r+b")
pdf_content.binmode
send_data pdf_content.read, :filename=>'output.pdf', :disposition=>'inline', :type=>'application/pdf'
end
end
end
负责使用 PDFtk 填充和生成 PDF 的 pdf_stamper 类
require 'builder'
require 'open3'
class PdfStamper
def self.stamp(input_pdf, fields)
Open3.popen3("pdftk #input_pdf fill_form - output -") do |stdin, stdout, stderr|
stdin << generate_xfdf(fields, File.basename(input_pdf))
stdin.close
yield stdout
stdout.close
stderr.close
end
end
def self.generate_xfdf(fields, filename)
xml = Builder::XmlMarkup.new
xml.instruct!
xml.xfdf("xmlns" => "http://ns.adobe.com/xfdf/", "xml:space" => "preserve")
xml.f :href => filename
xml.fields
fields.each do |field, value|
xml.field(:name => field)
if value.is_a? Array
value.each |item| xml.value(item.to_s)
else
xml.value(value.to_s)
end
end
xml.target!
end
end
【讨论】:
它会生成mi损坏的文件...:/以上是关于无法使用 PDFtk 生成正确的 PDF 文件的主要内容,如果未能解决你的问题,请参考以下文章
Windows批处理脚本在子文件夹中查找最大的PDF文件并使用Ghostscript和`pdftk`在页脚中打印路径
Rotativa 生成的 PDF 无法正确呈现 - 分页符/元素中断
如何使用 pdfjam 或 pdftk 在 pdf 中添加页脚?