ruby-on-rails - WickedPDF 生成的带有神社的 PDF 文件上传不填充数据字段
问题描述
我正在从 Paperclip 迁移我的整个升级过程,并且在生成的 PDF 方面存在问题。
处理上传的子模型是一个名为quotepdf
在某些时候,quotepdf
会生成一个实例并有一个链接到它的附件。
这是为神社改编的quotepdf模型
class Quotepdf < ApplicationRecord
include QuotesAndInvoicesUploader::Attachment.new(:quote)
belongs_to :quotable, polymorphic: true
end
上传者:
class QuotesAndInvoicesUploader < Shrine
plugin :validation_helpers # to validate pdf
plugin :delete_raw
Attacher.validate do
validate_max_size 1.megabyte
validate_mime_type_inclusion ['application/pdf']
end
def generate_location(io, context)
type = context[:record].class.name.downcase if context[:record]
name = super
[type, name].compact.join("/")
end
end
以及使用 Wickedpdf 创建“quotepdf 记录”和 PDF 附件的 Sidekiq 工作人员:
class PhotographerQuotePdfWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(id)
@quote = Photographerquote.find(id)
ac = ActionController::Base.new()
pdf_string = ac.render_to_string pdf: 'photographerquote-'+@quote.hashed_id.to_s, template: "photographerquote/print_quote.pdf.erb", encoding: "UTF-8", locals: {pdfquote: @quote}
new_pdf = @quote.build_quotepdf
new_pdf.quote = StringIO.new(pdf_string)
new_pdf.save
end
end
使用回形针,它曾经可以正常工作。虽然使用神社,但没有任何内容保存到新的“quotepdf”记录的“quote_data”列中。工人也没有返回错误。
缓存文件确实已上传到 S3 存储桶,因此可以正确生成 PDF 文件。最终文件丢失。
编辑
通过剥离我的上传器使其工作:
class QuotesAndInvoicesUploader < Shrine
def generate_location(io, context)
type = context[:record].class.name.downcase if context[:record]
name = super
[type, name].compact.join("/")
end
end
但我不明白为什么它之前失败了:文件只有 22KB,确实是 PDF。不能是验证问题..
编辑 2
Ok mimetype 检测到的确实是null
{"id":"devispdf/04aa04646f73a3710511f851200a2895","storage":"store","metadata":{"filename":null,"size":21613,"mime_type":null}}
虽然我的初始化程序有Shrine.plugin :determine_mime_type
解决方案
在您的后台作业中,尝试查看此输出:
Shrine.determine_mime_type(StringIO.new(pdf_string))
如果是nil
,那么我会建议尝试不同的分析器(例如:mimemagic
或:marcel
)。
Shrine.plugin :determine_mime_type, analyzer: :mimemagic
# or
Shrine.plugin :determine_mime_type, analyzer: :marcel
如果失败,您还可以使用基于扩展名的分析器,例如:mime_types
or :mini_mime
,并在后台作业中分配一个带有扩展名的临时文件:
tempfile = Tempfile.new(["quote", ".pdf"], binmode: true)
tempfile.write pdf_string
tempfile.open # flush & rewind
new_pdf = @quote.build_quotepdf
new_pdf.quote = tempfile
new_pdf.save! # fail loudly if save fails
或者,由于您附加在后台作业中,您可以完全避免临时存储和验证:
pdf_file = StringIO.new(pdf_string)
uploaded_file = new_pdf.quote_attacher.store!(pdf_file)
new_pdf.quote_data = uploaded_file.to_json
new_pdf.save!
推荐阅读
- c - 使用循环在c中绘制一个编号的三角形
- javascript - scrollTop = scrollHeight 在聊天机器人中不起作用
- c# - 处理 ASP.NET Core Web API 对象属性绑定
- bash - 如何替换一行中已知位置的未知值?
- excel - Range 类的 Excel VBA AutoFill 方法失败-仅存在一条记录时失败
- vega-lite - 如何在 Vega LIte 中创建相对标记位置
- function - 如何在 vim statusline 中显示字符串的实例数
- reactjs - 用 jest 测试 react-map-gl 和 react 测试库超时
- c# - C# 允许将值与接口的属性相关联
- javascript - 无法连接到 mongo db 数据库,显示超时错误