2013-07-03 44 views
2

我正在使用Ruby on Rails 3開發Web應用程序。該應用程序的功能之一是使用來自MySQL數據庫的數據來填充Adobe設計的PDF模板表單LiveCycle Designer。無法使用PDFtk生成正確的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>,每次輸出後HEX值都會改變。

生成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 

我懷疑真正的問題是在下面的兩個代碼片段之一。我剛開始學習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應用程序,而且我仍然得到相同的錯誤RS。周圍挖在網絡上後,我改變了代碼在我的控制器,以這樣的:

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解釋換行符或類似的方式有關?

+0

我更新了我的問題PDF的pdf_stamper類。請參閱我的帖子末尾的更新#1。 – Nik

回答

0

在通過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

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 
+1

它生成mi損壞的文件...:/ – mArtinko5MB