ruby-on-rails 如何创建缩略图的第一个PDF页面与载波

mhd8tkvw  于 2023-10-21  发布在  Ruby
关注(0)|答案(4)|浏览(91)

我处理缩略图的PDF文件以这种方式:

version :thumb do
    process :resize_to_limit => [260, 192]
    process :convert => :jpg
    process :set_content_type
  end

  def set_content_type(*args)
    self.file.instance_variable_set(:@content_type, "image/jpeg")
  end

但是,当PDF文件是多页的,它会产生一个JPG文件中的所有页面的缩略图。有没有办法只为首页制作缩略图?

4jb9z9bj

4jb9z9bj1#

今年早些时候,我提交了一个patch来做这件事。使用自定义处理器:

def cover 
  manipulate! do |frame, index|
    frame if index.zero?
  end
end

process :cover
cotxawn7

cotxawn72#

伟大的解决方案由坦齐布!谢谢
所以我可以这样做:

def cover 
    manipulate! do |frame, index|
      frame if index.zero?
    end
  end

并将其用于拇指一代

version :thumb do
    process :cover    
    process :resize_to_fill => [50, 50, Magick::NorthGravity]
    process :convert => 'png'
  end

好极了!

qlvxas9a

qlvxas9a3#

我在寻找解决这个问题的方法时遇到了这篇文章。当你把一个pdf转换成jpeg时,它会创建一个所有页面首尾相连的长pdf,所以你需要把图像裁剪成你想要的长宽比,然后丢弃剩下的。下面是我最终使用的:

version :thumb_safari do #special version for safari and ios
  process :resize_to_fit => [200,200]
  process :convert => 'jpg'
  process :paper_shape
  def full_filename (for_file = model.logo.file)
     super.chomp(File.extname(super)) + '.jpg'
  end     
end

version :thumb do #all browsers except safari
  process :resize_to_fit => [200,200]
  process :convert => 'jpg' #must convert to jpg before running paper shape
  process :paper_shape
  process :convert => 'jpg' #after running paper_shape it will default to original file type
  def full_filename (for_file = model.logo.file)
    super.chomp(File.extname(super)) + '.jpg'
  end
end

def paper_shape
   manipulate! do |img|
     if img.rows*4 != img.columns*3
       width=img.columns
       height=img.columns/3*4
       img.crop!(0,0,width,height,true)
     else
       img
     end
   end
 end

在控制器/视图中,我使用了useragent gem并这样做:
documents_controller.rb

def index
  @user_agent=UserAgent.parse(request.user_agent)
  @search = Document.search(params[:q])
end

index.html.rb

<% if @user_agent.browser.downcase == 'safari' %>
<%= link_to(image_tag(doc.pdfdoc_url(:thumb_safari).to_s, :class=>"dropshadow", :size => "150x225"), doc.pdfdoc_url)%>
<% else %>
<%= link_to(image_tag(doc.pdfdoc_url(:thumb).to_s, :class=>"dropshadow", :size => "150x225"), doc.pdfdoc_url)%>
<% end %>

毫无疑问,有一个更好的方法来做到这一点,但这是目前的工作。

3ks5zfa0

3ks5zfa04#

结论

@tanzeeb提出的当前解决方案对于大多数图像/PDF文件都很有效,并且manipulate函数是一种有用的动态方式来操作整个PDF,但是它太广泛了,在生成缩略图时被认为是一种可行的方法,其主要目标是只操作PDF的第一页。
为什么?
这段manipulate!代码强制在继续之前读取整个文件,稍后还会遍历整个文件。这与生成缩略图是违反直觉的,可能是一个资源问题。

其他解决方案

manipulate内部,有一个&read_block被传递到::Magic::Image.read/1,它可能被用来改变传递到read本身的图像数据,其中一个read_options指定来自current_path的特定数据位。
不过,CarrierWave文档在描述它的可能用途方面过于肤浅,实际上在描述它的代码使用方面是错误的。所以这对我来说是个死胡同

代码

我最终从manipulate!函数中获取了一堆代码,以便在我自己的上传程序中使用,在那里我删除了一些在生成缩略图时不使用的功能。

# @doc Returns the first page of a file
  version :thumb, :if => :thumbable? do
    process :cover
    process convert: "jpg"
    def full_filename(filename = model.file.filename) = "#{filename.split(".").first}.jpg"
    def style = :thumb

    # @doc This is an overridden function from the `manipulate!` function defined in CarrierWaves library
    # @doc I removed the ability to pass in options, or a block to the function to use in processing the image.
    # @doc This seemed to be the route to go because there isn't many maintainers available on CarrierWave and the documentation is trash.
    def cover
      cache_file
      push_frames(get_frames)
    rescue ::Magick::ImageMagickError
      raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.processing_error")
    end

    private

    # @doc This will store the file available on the uploader in the cache, unless it is already cached.
    def cache_file
      cache_stored_file! unless cached?
    end

    # @doc This will utilize RMagick to create an image from an altered current_path variable
    # @doc Create a new ImageList, and store the image created as the first frame
    def get_frames
      path = "#{current_path}[0]"
      image = ::Magick::Image.read(path)
      frames = ::Magick::ImageList.new
      frames << image.first
    end

    # @doc This will persist the frames created as an ImageList into the file on the uploader, essentially replacing the original pdf with the modified pdf.
    def push_frames(frames)
      frames.write(current_path)
    end

    # @doc This will destroy the ImageList that is allocating memory.
    def destroy_image(frames)
      frames.try(:destroy!)
    end
  end

相关问题