Предварительный просмотр pdf Rails 5 с Shrine Gem

Я использую Shrine Gem для загрузки изображений, и мне было интересно, как, если возможно, я могу показать предварительный просмотр 1-й страницы в моем шаблон, например, показ изображения для каждого слова. Я нормально использую jQuery или другую библиотеку. Ниже приведен мой код для загрузки файла, включая инициализатор Shrine и файл загрузчика.

просмотр

...
<div class="col-md-4 upload-block">
    <%= f.label :spec_sheet, 'Spec Sheet' %>
      <% if @product.spec_sheet.present? %>
        <div class="product-image">
          <%= image_tag(@product.spec_sheet_url(:thumb)) %>
            <div class="input-checkbox input-checkbox--switch">
              <input name="product[remove_spec_sheet]" type="hidden" value="0">
              <input id="checkbox-switch" type="checkbox" name="product[remove_spec_sheet]">
              <label for="checkbox-switch"></label>
            </div>
            <span>Remove Spec Sheet</span>
        </div>
        <% end %>
          <%= f.hidden_field :spec_sheet, value: @product.cached_spec_sheet_data %>
            <%= f.file_field :spec_sheet %>
  </div>
...

инициализатор

require 'shrine'
require 'shrine/storage/file_system'

Shrine.storages = {
    cache: Shrine::Storage::FileSystem.new('public', prefix: 'uploads/cache'),
    store: Shrine::Storage::FileSystem.new('public', prefix: 'uploads/store'),
}

Shrine.plugin :activerecord
Shrine.plugin :remove_attachment
Shrine.plugin :delete_raw
Shrine.plugin :cached_attachment_data # for forms 

загрузчик

require 'image_processing/mini_magick'
class ImageUploader < Shrine
  MAX_IMAGE_SIZE_MB = 5
  include ImageProcessing::MiniMagick

  plugin :determine_mime_type
  plugin :remove_attachment
  plugin :store_dimensions
  plugin :validation_helpers
  plugin :processing
  plugin :versions
  plugin(:default_url) { |_|  '/img/preview-not-available.jpg' }

  Attacher.validate do
    validate_max_size MAX_IMAGE_SIZE_MB.megabytes, message: "is too large (max is #{MAX_IMAGE_SIZE_MB} MB)"
    validate_mime_type_inclusion %w[image/jpeg image/jpg image/png image/gif]
  end

  process(:store) do |io|
    original = io.download

    size_1500 = resize_to_limit!(original, 1500, 600)
    size_500 = resize_to_limit(size_1500,  500, 500)
    size_300 = resize_to_limit(size_500,  300, 300)

    {original: size_1500, medium: size_500, thumb: size_300 }
  end
end

person Charles Smith    schedule 04.12.2017    source источник
comment
Привет! Похоже, вы какое-то время сталкивались с переполнением стека, поэтому вы должны знать, что мы ожидаем, что вы сначала попробуете это сами, а затем придете к нам с обнаруженной вами ошибкой;) что вы пытались исправить превью работает? что вы наблюдаете вместо этого? такие вещи;)   -  person Taryn East    schedule 05.12.2017


Ответы (1)


Если вы хотите показать превью PDF-файла, вам нужно будет сгенерировать его на стороне сервера. В этом случае лучше всего использовать прямую загрузку (см. demo для примера со стороны клиента. выполнение).

Затем вы можете сгенерировать предварительный просмотр PDF-файлов при прямой загрузке:

# config/initializers/shrine.rb
Shrine.plugin :determine_mime_type

# app/models/image_uploader.rb
class ImageUploader < Shrine
  plugin :processing
  plugin :versions

  process(:upload) do |io, context|
    if Shrine.determine_mime_type(io) == "application/pdf"
      preview = Tempfile.new(["shrine-pdf-preview", ".pdf"], binmode: true)
      begin
        IO.popen *%W[mutool draw -F png -o - #{io.path} 1], "rb" do |command|
          IO.copy_stream(command, preview)
        end
      rescue Errno::ENOENT
        fail "mutool is not installed"
      end

      preview.open # flush & rewind
    end

    versions = { original: io }
    versions[:preview] = preview if preview && preview.size > 0
    versions
  end
end
  • upload_endpoint устанавливает действие обработки :upload, так что значение process(:upload)
  • мы используем rb вместо IO.popen, чтобы Ruby использовал двоичную кодировку, которая является более безопасной и кроссплатформенной.
  • Kernel#spawn и любые методы, использующие spawn (system, IO.popen и т. Д.), Будут вызывать Errno::ENOENT, если команда оболочки не найдена
  • мы используем *%W[] вместо просто "", чтобы Ruby избегал оболочки (и, следовательно, любых возможных проблем с экранированием оболочки) и передавал команду непосредственно в ОС
  • мы проверяем, является ли preview файл непустым, потому что он будет пустым в случае сбоя команды mutool (в этом случае мы, вероятно, захотим отказаться от отображения предварительного просмотра)

Результат POST-запроса к upload_endpoint теперь будет содержать идентификатор загруженного файла предварительного просмотра, который вы можете использовать для генерации URL-адреса для предварительного просмотра. В вашем случае это будет "/uploads/cache" + id.

Обратите внимание, что это означает, что вам придется немного изменить код обработки, который вызывается, когда кэшированный файл перемещается в постоянное хранилище. В блоке process(:store) do |io, context| io теперь будет хешем версий, поэтому вы можете получить доступ к исходному кэшированному файлу через io[:original]. И не забудьте также включить файл предварительного просмотра в результат этого блока, так как вы, вероятно, захотите его сохранить.

process(:store) do |io, context|
  original = io[:original].download

  # processing...

  versions = io.dup
  versions[:small] = small
  versions[:medium] = medium
  # ...
  versions
end
person janko-m    schedule 05.12.2017