如何使用Carrierwave和MiniMagick(Ruby on Rails)将PDF转换为图像数组

我正在将上传的PDF转换为图像,每页只有一个图像。 我已经想出如何使用MiniMagick::Tool::Convert生成图像,但我不知道如何为Uploader编写version块,以便我可以访问图像URL数组。

到目前为止,这是我的上传者:

 class DocumentUploader < CarrierWave::Uploader::Base include CarrierWave::MiniMagick storage :file # storage :fog def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end version :jpg do process :convert_to_images process :set_content_type_jpg def convert_to_images(*args) image = MiniMagick::Image.open(current_path) image.pages.each_with_index do |page, index| MiniMagick::Tool::Convert.new do |convert| convert.background 'white' convert.flatten convert.density 300 convert.quality 95 convert << page.path convert << "#{CarrierWave.root}/#{store_dir}/image-#{index}.jpg" end end end end def set_content_type_jpg(*args) self.file.instance_variable_set(:@content_type, "image/jpg") end # Add a white list of extensions which are allowed to be uploaded. def extension_white_list %w(jpg jpeg gif png doc docx pdf) end end 

这会在正确的目录中生成image-0.jpgimage-1.jpg等。 但是现在我无法在我的视图中引用这些图像,甚至不知道有多少图像。 当我需要将图像上传到S3时,这也不起作用。 如何让Carrierwave处理此图像集合的文件存储,而不是单个图像?

看起来我可能还需要添加一个新的数据库列来存储页面数。 有没有办法让我的上传者根据这个计数返回一组图像URL?

我也愿意转向另一个gem。 使用Paperclip,Shrine或Refile会更容易吗?

使用Shrine,您可以使每个页面成为不同的版本:

 class ImageUploader < Shrine plugin :versions plugin :processing process(:store) do |io, context| pdf = io.download versions = {} image = MiniMagick::Image.new(pdf.path) image.pages.each_with_index do |page, index| page_image = Tempfile.new("version-#{index}", binmode: true) MiniMagick::Tool::Convert.new do |convert| convert.background 'white' convert.flatten convert.density 300 convert.quality 95 convert << page.path convert << page_image.path end page_image.open # refresh updated file versions[:"page_#{index + 1}"] = page_image end versions end end 

假设您有一个Document模型,并且您将PDF附加到file附件字段,则可以使用Hash#values检索一个页面数组:

 pages = document.file.values pages #=> [...array of pages...] pages.count #=> number of pages