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

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

【问题讨论】:

  • 使用carrierwave gem会有所帮助

标签: ruby-on-rails ruby-on-rails-5 rails-activestorage


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

            【讨论】:

            • 应该始终在后端进行验证。任何使用都可以很容易地禁用它:)
            • 在使用直接上传时如何进行后端验证?该文件永远不会直接到达服务器。它必须是“事后”验证。
            猜你喜欢
            • 1970-01-01
            • 2021-09-20
            • 1970-01-01
            • 1970-01-01
            • 2020-07-06
            • 1970-01-01
            • 1970-01-01
            • 2020-12-09
            • 1970-01-01
            相关资源
            最近更新 更多