Ruby on Rails - Active Storage - 如何只接受 pdf 和 doc?

Posted

技术标签:

【中文标题】Ruby on Rails - Active Storage - 如何只接受 pdf 和 doc?【英文标题】:Ruby on Rails - Active Storage - how to accept only pdf and doc? 【发布时间】:2018-06-29 03:57:55 【问题描述】:

是否可以使用 Active Storage 添加验证以仅接受 .pdf 和 .doc 文件?

【问题讨论】:

使用carrierwave gem会有所帮助 【参考方案1】:

并不总是需要为几行代码添加 gem。这是一个基于上述示例的小改动的工作示例。

validate :logo_content_type, if: ->  logo.attached? 


def logo_content_type
  allowed = %w[image/jpeg image/jpeg image/webp image/png]
  if allowed.exclude?(logo.content_type)
    errors.add(:logo, message: 'Logo must be a JPG, JPEG, WEBP or PNG')
  end
end

【讨论】:

【参考方案2】:

我在看https://gist.github.com/lorenadl/a1eb26efdf545b4b2b9448086de3961d

在你看来,你必须做这样的事情

<div class="field">
  <%= f.label :deliverable %>
  <%= f.file_field :deliverable, direct_upload: true, 
    accept: 'application/pdf, 
    application/zip,application/vnd.openxmlformats-officedocument.wordprocessingml.document' %>
 </div>

现在在你的模型上,你可以做这样的事情

class User < ApplicationRecord
  has_one_attached :document

  validate :check_file_type

  private

  def check_file_type
    if document.attached? && !document.content_type.in?(%w(application/msword application/pdf))
      document.purge # delete the uploaded file
      errors.add(:document, 'Must be a PDF or a DOC file')
    end
  end
end

希望对你有帮助

【讨论】:

【参考方案3】:

+1 将gem 'activestorage-validator' 与 ActiveStorage 一起使用

在您的模型中,您可以通过这种方式验证 docdocxpdf 格式:

has_one_attached :cv
validates :cv, blob:  content_type: ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/pdf'], size_range: 0..5.megabytes 

【讨论】:

【参考方案4】:

目前您必须编写自己的验证器来查看附件的 MIME 类型:

class Item
  has_one_attached :document

  validate :correct_document_mime_type

  private

  def correct_document_mime_type
    if document.attached? && !document.content_type.in?(%w(application/msword application/pdf))
      document.purge # delete the uploaded file
      errors.add(:document, 'Must be a PDF or a DOC file')
    end
  end
end

此外,还有一些有用的快捷方法 image?audio?video?text? 可以检查多种 mime 类型。

【讨论】:

application/msword 不是 word 文档的 content_type。它是application/vnd.openxmlformats-officedocument.wordprocessingml.document,如下所述。 @Archonic OP 询问了.doc(旧的 MS Word 格式),在这种情况下 MIME 类型实际上是 application/msword。您提到的类型适用于较新的基于 XML 的.docx。我猜大多数人都想在他们的验证器中使用这两者。 对,我的错! Activestorage 应该在 rails 6 中进行适当的验证。同时,我发现我还需要包含 document.purge 和 errors.add,否则该 blob 将成为孤立对象。 此解决方案不会阻止文件上传,只会阻止文件保存。【参考方案5】:

我正在使用 ActiveStorage 进行直接上传。由于验证器还不存在,我只是简单地覆盖了DirectUploadsController Create 方法:

# This is a kind of monkey patch which overrides the default create so I can do some validation.
# Active Storage validation wont be released until Rails 6.
class DirectUploadsController < ActiveStorage::DirectUploadsController
  def create
    puts "Do validation here"
    super
  end
end

还需要覆盖路由:

  post '/rails/active_storage/direct_uploads', to: 'direct_uploads#create'

【讨论】:

【参考方案6】:
class Book < ApplicationRecord
  has_one_attached :image
  has_many_attached :documents

  validate :image_validation
  validate :documents_validation

  def documents_validation
    error_message = ''
    documents_valid = true
    if documents.attached?
      documents.each do |document|
        if !document.blob.content_type.in?(%w(application/xls application/odt application/ods pdf application/tar application/tar.gz application/docx application/doc application/rtf application/txt application/rar application/zip application/pdf image/jpeg image/jpg image/png))
          documents_valid = false
          error_message = 'The document wrong format'
        elsif document.blob.byte_size > (100 * 1024 * 1024) && document.blob.content_type.in?(%w(application/xls application/odt application/ods pdf application/tar application/tar.gz application/docx application/doc application/rtf application/txt application/rar application/zip application/pdf image/jpeg image/jpg image/png))
          documents_valid = false
          error_message = 'The document oversize limited (100MB)'
        end
      end
    end
    unless documents_valid
      errors.add(:documents, error_message)
      self.documents.purge
      DestroyInvalidationRecordsJob.perform_later('documents', 'Book', self.id)
    end
  end

  def image_validation
    if image.attached?
      if !image.blob.content_type.in?(%w(image/jpeg image/jpg image/png))
        image.purge_later
        errors.add(:image, 'The image wrong format')
      elsif image.blob.content_type.in?(%w(image/jpeg image/jpg image/png)) && image.blob.byte_size > (5 * 1024 * 1024) # Limit size 5MB
        image.purge_later
        errors.add(:image, 'The image oversize limited (5MB)')
      end
    elsif image.attached? == false
      image.purge_later
      errors.add(:image, 'The image required.')
    end
  end
end

在工作中销毁

class DestroyInvalidationRecordsJob < ApplicationJob
  queue_as :default

  def perform(record_name, record_type, record_id)
    attachments = ActiveStorage::Attachment.where(name: record_name, record_type: record_type, record_id: record_id)
    attachments.each do |attachment|
      blob = ActiveStorage::Blob.find(attachment.blob_id)
      attachment.destroy
      blob.destroy if blob.present?
    end
  end
end

【讨论】:

【参考方案7】:

有一个 gem 可以为主动存储提供验证

gem 'activestorage-validator'

https://github.com/aki77/activestorage-validator

  validates :avatar, presence: true, blob:  content_type: :image 
  validates :photos, presence: true, blob:  content_type: ['image/png', 'image/jpg', 'image/jpeg'], size_range: 1..5.megabytes 

【讨论】:

错字precence 应该是presence 此代码不是仅在附件是图像时才验证吗? pdf的代码应该是什么?我正在为此苦苦挣扎。【参考方案8】:

由于 ActiveStorage 还没有验证,我在我的表单中发现了以下帮助。

<div class="field">
  <%= f.label :deliverable %>
  <%= f.file_field :deliverable, direct_upload: true, 
    accept: 'application/pdf, 
    application/zip,application/vnd.openxmlformats-officedocument.wordprocessingml.document' %>
 </div>

【讨论】:

应该始终在后端进行验证。任何使用都可以很容易地禁用它:) 在使用直接上传时如何进行后端验证?该文件永远不会直接到达服务器。它必须是“事后”验证。

以上是关于Ruby on Rails - Active Storage - 如何只接受 pdf 和 doc?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails - Active Storage - 如何只接受 pdf 和 doc?

Ruby on Rails 变量在视图中显示 Active Record 数据而不是整数

Ruby on Rails。如何在 :belongs to 关系中使用 Active Record .build 方法?

Active Admin - 根据第一个下拉菜单刷新第二个下拉菜单,Ruby on Rails

在 Ruby on Rails 4 中使用 Active Record 或 Squeel Gem 重写 SQL 查询

ruby on rails 在model中使用enum的注意事项