Как конвертировать PDF в массив изображений с помощью Carrierwave и MiniMagick (Ruby on Rails)
Я конвертирую загруженные PDF-файлы в изображения, по одному изображению на страницу. Я понял, как генерировать изображения, используя MiniMagick::Tool::Convert
, но я не знаю, как написать version
блок для Uploader, чтобы я мог получить доступ к массиву 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.jpg
, image-1.jpg
и т. д. в правильном каталоге. Но теперь у меня нет возможности ссылаться на эти изображения в моих представлениях или даже знать, сколько их. Это также не будет работать, когда мне нужно загрузить изображения на S3. Как я могу заставить Carrierwave обрабатывать хранилище файлов для этой коллекции изображений вместо одного изображения?
Похоже, мне, вероятно, потребуется добавить новый столбец базы данных для хранения количества страниц. Есть ли способ заставить мой загрузчик возвращать массив URL изображений, основываясь на этом количестве?
Я также готов переключиться на другой драгоценный камень. Разве это будет проще с Paperclip, Shrine или Refile?
1 ответ
С помощью 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