关于ruby on rails:如何使用回形针将多页pdf缩略图化

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