How to thumbnail a multi-page pdf with paperclip
我想让回形针为上传的多页PDF文件的每一页创建2个缩略图。
我正在运行Paperclip 2.3.1.1,并在我的Asset模型中使用它:
1 2 | has_attached_file :asset, :styles => { :medium =>"800x600>", :thumb =>"100x100>" } |
因此,当我上传一个3页的pdf文件时,我希望这会在每页上创建2个大拇指(一个800x600像素,另一个较小的图像100x100)。相反,我创建了3个文件夹(拇指,中号,原始)-原始文件夹包含origianl pdf文件,而拇指和中号每个都包含一个pdf,而pdf的第一页都被像素化了。
我需要怎么做才能使回形针为pdf的每一页创建2个大拇指?理想情况下,我希望每页这样一张图片(创建6张图片):
assets / 1 / medium / file-0.png
资产/1/medium/file-1.png
assets / 1 / medium / file-2.png
资产/ 1 /缩略图/文件-0.png
资产/ 1 /拇指/file-1.png
assets / 1 / thumb / file-2.png
有人知道该怎么做吗?我需要自定义处理器吗?如果是这样,处理器将是什么样?
谢谢。
这是我执行类似任务的方式。
文档模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class Document < ActiveRecord::Base has_many :pages, :dependent => :destroy has_attached_file :asset after_asset_post_process :make_pages private def make_pages if valid? Paperclip.run('convert',"-quality #{Page::QUALITY} -density #{Page::DENSITY} #{asset.queued_for_write[:original].path} #{asset.queued_for_write[:original].path}%d.png") images = Dir.glob("#{asset.queued_for_write[:original].path}*.png").sort_by do |line| line.match(/(\\d+)\\.png$/)[1].to_i end images.each do |page_image| pages.build(:asset => File.open(page_image)) end FileUtils.rm images end end end |
页面模型:
1 2 3 4 5 6 7 8 9 10 | class Page < ActiveRecord::Base belongs_to :document has_attached_file :asset QUALITY = 100 DENSITY = '80x80' end |
我对此有半途而废的解决方案...但是它不是很优雅。我真的很想提出更好的建议,但我想还是应该分享。
我从定义一堆新样式开始,每页一个...直到我想要处理的许多页面。 (我知道这很愚蠢,但是我不知道如何访问回形针中的路径插值,以便每个页面都可以正确地保存/删除在存储中,除非每个图像都有独特的样式)
1 2 3 4 5 6 7 8 | { ... :page_0 => {:geometry=>'800[0]', :format=>:png, :processors=>[:multipage_thumbnail]}, :page_1 => {:geometry=>'800[1]', :format=>:png, :processors=>[:multipage_thumbnail]}, :page_2 => {:geometry=>'800[2]', :format=>:png, :processors=>[:multipage_thumbnail]}, :page_3 => {:geometry=>'800[3]', :format=>:png, :processors=>[:multipage_thumbnail]}, :page_4 => {:geometry=>'800[4]', :format=>:png, :processors=>[:multipage_thumbnail]}, :page_5 => {:geometry=>'800[5]', :format=>:png, :processors=>[:multipage_thumbnail]}, } |
然后...我有一个自定义处理器,该处理器从Thumbnail处理器子类化,并带有一些额外的逻辑,用于在正确的页面#上运行convert命令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | module Paperclip # Handles thumbnailing images that are uploaded. class MultipageThumbnail < Thumbnail # Creates a Thumbnail object set to work on the +file+ given. It # will attempt to transform the image into one defined by +target_geometry+ # which is a"WxH"-style string. +format+ will be inferred from the +file+ # unless specified. Thumbnail creation will raise no errors unless # +whiny+ is true (which it is, by default. If +convert_options+ is # set, the options will be appended to the convert command upon image conversion def initialize file, options = {}, attachment = nil @page = options[:geometry].match(/\\[(\\d+)\\]/)[1] rescue 0 @page ||= 0 options[:geometry] = options[:geometry].sub(/\\[\\d+\\]/, '') super end # Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile # that contains the new image. def make return nil if @page >= page_count src = @file dst = Tempfile.new([@basename, @format].compact.join(".")) dst.binmode begin options = [ source_file_options, "#{ File.expand_path(src.path) }[#{@page}]", transformation_command, convert_options, "#{ File.expand_path(dst.path) }" ].flatten.compact success = Paperclip.run("convert", *options) rescue PaperclipCommandLineError => e raise PaperclipError,"There was an error processing the thumbnail for #{@basename}" if @whiny end dst end def page_count @page_count ||= begin files = Paperclip.run("identify","#{@file.path}") files.split(/\ /).size rescue PaperclipCommandLineError 1 end end end end |