与神殿宝石的Rails 5 pdf预览 [英] Rails 5 pdf preview with Shrine Gem
问题描述
我正在使用神殿宝石上传图片,并且想知道如何显示第一页在我的模板中预览,例如显示图片.我可以使用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
的方法(system
,IO.popen
等)在找不到shell命令时会提高Errno::ENOENT
- 我们使用
*%W[]
而不是""
,以便Ruby避免使用shell(并避免任何可能的shell逃逸问题),并将命令直接传递给OS - 我们检查
preview
文件是否为非空文件,因为如果mutool
命令失败(在这种情况下,我们可能希望退回到不显示预览)的情况下文件将为空 - the
upload_endpoint
sets the:upload
processing action, so that's the meaning ofprocess(:upload)
- we use
rb
forIO.popen
so that Ruby uses binary encoding, which is more safe and cross-platform Kernel#spawn
and any methods that usespawn
(system
,IO.popen
etc.) will raiseErrno::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 themutool
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屋!