module RailsConnector # # This module provides an interface for generating PDF files. # module FopOnRails # # Is raised if the response was not 200. # class DownloadError < RuntimeError; end READ_TIMEOUT = 300 # # Generates a PDF from xml_location and xsl_location and returns its # path in the file system. # # If the file xml_location doesn't already exist, then xml_location # and xsl_location are interpreted as URLs and will be downloaded before # the PDF is generated. # # If the download of xml_location or xsl_location fails, then # the {RailsConnector::FopOnRails::DownloadError} is raised. # # To generate a PDF, the given XML must be valid. If for some reasons it is not, then you can use the # tidy option to repair it. # # If the PDF generation fails, then the {RailsConnector::Fop::GenerationFailed} error # is raised. # # Example: # # RailsConnector::FopOnRails.generate_pdf('/tmp/test.xml', '/tmp/test.xsl') # # This will generate a PDF and return its path # # RailsConnector::FopOnRails.generate_pdf('http://mywebsite.com/test.xml', 'http://mywebsite.com/test.xsl', true) # # This will download both files, repair the XML, generate a PDF, and return its path # def self.generate_pdf(xml_location, xsl_location, tidy = false) log("\nStarting PDF generation...") w_dir = File.join(Rails.root, %w(tmp fop_on_rails), $$.to_s) FileUtils.rm_rf(w_dir) FileUtils.mkdir_p(w_dir) pdf = "#{w_dir}/pdf" if File.exist?(xml_location) xml = xml_location xsl = xsl_location log("\trepairing XML") FopOnRails::Document.repair(xml) else xml = "#{w_dir}/xml" xsl = "#{w_dir}/xsl" log("\tgetting XSL source from #{xsl_location}") download(xml_location, xml) log("\tgetting XML source from #{xml_location}") download(xsl_location, xsl) end if tidy log("\trepairing XML") FopOnRails::Document.repair(xml, xml_location) end log("\tgenerating PDF\n\n") Fop.generate_pdf(xml, xsl, pdf) return pdf end private def self.download(src, dest) url = URI.parse(src) http = Net::HTTP.new(url.host, url.port) http.read_timeout = READ_TIMEOUT resp = http.get(url.request_uri) unless resp.kind_of?(Net::HTTPSuccess) raise DownloadError, "Could not download #{src}" end File.open dest, 'w' do |f| f.write resp.body end end def self.log(msg) Rails.logger.info(msg) end end end