Skip to content

Instantly share code, notes, and snippets.

@chsh
Created June 3, 2012 11:31
Show Gist options
  • Save chsh/2863121 to your computer and use it in GitHub Desktop.
Save chsh/2863121 to your computer and use it in GitHub Desktop.
Compose multiple pdf files into one content or file.
require 'tempfile'
# usage:
# pc = PDFComposer.new(file_or_content1[, file_or_content2 ...])
# content = pc.compose # compose all into content
# pc.compose(to_file_path) # output to 'to_file_path' :-)
class PDFComposer
def initialize(*args)
@sources = args.flatten
@tempfiles = []
end
def compose(path = nil)
@content ||= compose_content
if path
File.open(path, 'wb') do |f|
f.write @content
end
else
@content
end
end
private
def compose_content
source_files = files_from_sources
tf = Tempfile.new(%w(pdf-composer-output .pdf), encoding: 'BINARY')
tf.close
cmd_args = [self.class.gs_path, '-q', '-dNOPAUSE', '-dBATCH',
'-sDEVICE=pdfwrite', "-sOutputFile=#{tf.path}"]
cmd_args += source_files
success = system *cmd_args
raise "Fail to exec #{cmd_args.inspect}." unless success
content = tf.open.read
tf.close(true)
content
end
def files_from_sources
@sources.map do |source|
if source.is_a?(String)
if source.encoding != Encoding::BINARY && File.exist?(source)
source
else
tf = Tempfile.new(%w(pdf-composer .pdf), encoding: 'BINARY')
tf.write(source)
tf.close
@tempfiles << tf
tf.path
end
elsif source.is_a? Tempfile
source.path
end
end
end
def self.gs_path
@@gs_path ||= `which gs`.chomp
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment