首页 > 解决方案 > 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

标签: ruby-on-railsruby-on-rails-5.2shrine

解决方案


在您的后台作业中,尝试查看此输出:

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_typesor :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!

推荐阅读