ActiveStorage File Attachment Validation

前端 未结 7 536
暖寄归人
暖寄归人 2021-01-31 10:01

Is there a way to validate attachments with ActiveStorage? For example, if I want to validate the content type or the file size?

Something like Paperclip\'s approach wou

相关标签:
7条回答
  • 2021-01-31 10:16

    Well, it ain't pretty, but this may be necessary until they bake in some validation:

      validate :logo_validation
    
      def logo_validation
        if logo.attached?
          if logo.blob.byte_size > 1000000
            logo.purge
            errors[:base] << 'Too big'
          elsif !logo.blob.content_type.starts_with?('image/')
            logo.purge
            errors[:base] << 'Wrong format'
          end
        end
      end
    
    0 讨论(0)
  • 2021-01-31 10:19

    You can use awesome https://github.com/musaffa/file_validators gem

    class Profile < ActiveRecord::Base
      has_one_attached :avatar
      validates :avatar, file_size: { less_than_or_equal_to: 100.kilobytes },
        file_content_type: { allow: ['image/jpeg', 'image/png'] }
    end
    

    I'm using it with form object so I'm not 100% sure it is working directly with AR but it should...

    0 讨论(0)
  • 2021-01-31 10:29

    Copy contents of the ActiveStorage's DirectUploadsController in the app/controllers/active_storage/direct_uploads_controller.rb file and modify the create method. You can add authentication to this controller, add general validations on the file size or mime type, because create method of this controller creates the url for the file to be uploaded. So you can prevent any file upload by controlling size and mime type in this controller.

    A simple validation could be:

    # ...
    def create
      raise SomeError if blob_args[:byte_size] > 10240 # 10 megabytes
      blob = ActiveStorage::Blob.create_before_direct_upload!(blob_args)
      render json: direct_upload_json(blob)
    end
    # ...
    
    0 讨论(0)
  • 2021-01-31 10:31

    ActiveStorage doesn't support validations right now. According to https://github.com/rails/rails/issues/31656.


    Update:

    Rails 6 will support ActiveStorage validations.

    https://github.com/rails/rails/commit/e8682c5bf051517b0b265e446aa1a7eccfd47bf7

    Uploaded files assigned to a record are persisted to storage when the record
    is saved instead of immediately.
    In Rails 5.2, the following causes an uploaded file in `params[:avatar]` to
    be stored:
    ```ruby
    @user.avatar = params[:avatar]
    ```
    In Rails 6, the uploaded file is stored when `@user` is successfully saved.
    
    0 讨论(0)
  • 2021-01-31 10:32

    I found a way to validate and delete attachments with callback before_save. This is a useful approach because if you validate file during the transaction (and you want to purge it), after adding error and it will rollback deleting the attachment.

    before_save :check_logo_file, on: %i[create update]
    
    def check_favicon_content_type
        PartnerValidators::CustomPartnerFaviconValidator.new.validate(self)
    end
    
    module PartnerValidators
        class CustomPartnerFaviconValidator < ActiveModel::Validator
            ALLOWED_MIME_TYPES = %w(image/vnd.microsoft.icon image/x-icon image/png).freeze
            private_constant :ALLOWED_MIME_TYPES
    
            def validate(partner)
                if partner.favicon.attached? && invalid_content_type?(partner)
                    partner.errors.add(:favicon, I18n.t("active_admin.errors.favicon"))
                    partner.favicon.purge
                end
            end
    
            private
    
            def invalid_content_type?(partner)
                !partner.favicon.blob.content_type.in?(ALLOWED_MIME_TYPES)
            end
        end
    end
    
    0 讨论(0)
  • 2021-01-31 10:33

    Came across this gem: https://github.com/igorkasyanchuk/active_storage_validations

    class User < ApplicationRecord
      has_one_attached :avatar
      has_many_attached :photos
    
      validates :name, presence: true
    
      validates :avatar, attached: true, content_type: 'image/png',
                                         dimension: { width: 200, height: 200 }
      validates :photos, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg'],
                                         dimension: { width: { min: 800, max: 2400 },
                                                      height: { min: 600, max: 1800 }, message: 'is not given between dimension' }
    end
    
    0 讨论(0)
提交回复
热议问题