0

我正在使用Shrine Gem进行图像上传,并且想知道如果可能的话,我如何在我的模板中显示第一页预览,就像按说显示图像一样。我可以使用 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
4

1 回答 1

4

如果要显示 PDF 预览,则需要在服务器端生成它们。在这种情况下,最好使用直接上传(有关客户端实现的示例,请参见演示)。

然后,您可以在直接上传时生成 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)
  • 我们使用rbforIO.popen以便 Ruby 使用二进制编码,这样更安全且跨平台
  • Kernel#spawn当找不到 shell 命令时,任何使用spawn(systemIO.popen) 的方法都会引发Errno::ENOENT
  • 我们使用*%W[]而不是仅仅""为了让 Ruby 避免 shell(以及任何可能的 shell 转义问题)并将命令直接传递给操作系统
  • 我们检查preview文件是否为非空,因为如果命令失败,它将为空mutool(在这种情况下,我们可能希望退回到不显示预览)

POST 请求的结果upload_endpoint现在将包含预览的上传文件 ID,您可以使用它来生成预览的 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
于 2017-12-05T11:44:49.493 回答