与神殿宝石的Rails 5 pdf预览 [英] Rails 5 pdf preview with Shrine Gem

查看:74
本文介绍了与神殿宝石的Rails 5 pdf预览的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用神殿宝石上传图片,并且想知道如何显示第一页在我的模板中预览,例如显示图片.我可以使用jQuery或其他库.以下是我用于文件上传的代码,包括我的Shrine初始化程序和上传器文件.

I am using Shrine Gem for image uploads and was wondering how, if possible, can I show a 1st page preview in my template like showing an image per-say. I am ok with using jQuery or other library. Below is my code for the file upload, including my Shrine initializer and uploader file.

视图

...
<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

推荐答案

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

If you want to show PDF previews, you'll need to generate them on the server side. In that case it's best to use direct uploads (see the demo for an example of a client side implementation).

然后您可以在直接上传时生成PDF预览:

You can then generate PDFs preview on direct upload:

# 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的方法(systemIO.popen等)在找不到shell命令时会提高Errno::ENOENT
  • 我们使用*%W[]而不是"",以便Ruby避免使用shell(并避免任何可能的shell逃逸问题),并将命令直接传递给OS
  • 我们检查preview文件是否为非空文件,因为如果mutool命令失败(在这种情况下,我们可能希望退回到不显示预览)的情况下文件将为空
    • the upload_endpoint sets the :upload processing action, so that's the meaning of process(:upload)
    • we use rb for IO.popen so that Ruby uses binary encoding, which is more safe and cross-platform
    • Kernel#spawn and any methods that use spawn (system, IO.popen etc.) will raise Errno::ENOENT when shell command was not found
    • we use *%W[] instead of just "" so that Ruby avoids the shell (and with that any possible shell escaping issues) and passes the command directly to the OS
    • we check whether the preview file is nonempty because it will be empty in case the mutool command failed (in this case we probably want to fall back to not displaying a preview)
    • upload_endpoint的POST请求的结果现在将包含预览的上载文件ID,可用于生成预览的URL.在您的情况下为"/uploads/cache" + id.

      The result of the POST request to the upload_endpoint will now contain the uploaded file ID of the preview, which you can use to generate the URL to the preview. In your case that would be "/uploads/cache" + id.

      请注意,这意味着您必须稍微修改将缓存文件提升为永久存储时调用的处理代码.在process(:store) do |io, context|块中,io现在将是版本的哈希,因此您可以通过io[:original]访问原始缓存的文件.并且请确保还将预览文件包含在该块的结果中,因为您可能希望保留它.

      Note that this means you'll have to slightly modify the processing code that is called when cached file is promoted to permanent storage. In the process(:store) do |io, context| block the io will now be a hash of versions, so you can access the original cached file via io[:original]. And be sure to also include the preview file in the result of that block, as you'll likely want to keep it.

      process(:store) do |io, context|
        original = io[:original].download
      
        # processing...
      
        versions = io.dup
        versions[:small] = small
        versions[:medium] = medium
        # ...
        versions
      end
      

      这篇关于与神殿宝石的Rails 5 pdf预览的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆