web-dev-qa-db-fra.com

ActiveStorage Validation des pièces jointes

Existe-t-il un moyen de valider les pièces jointes avec ActiveStorage? Par exemple, si je veux valider le type de contenu ou la taille du fichier?

Quelque chose comme l'approche de Paperclip serait génial!

  validates_attachment_content_type :logo, content_type: /\Aimage\/.*\Z/
  validates_attachment_size :logo, less_than: 1.megabytes
13
Tom Rossi

Eh bien, ce n'est pas joli, mais cela peut être nécessaire jusqu'à ce qu'ils fassent l'objet d'une 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
12
Tom Rossi

ActiveStorage ne supporte pas les validations pour le moment. Selon https://github.com/Rails/rails/issues/31656 .


Mettre à jour:

Rails 6 supportera les validations ActiveStorage.

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.
7
swordray

Vous pouvez utiliser 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

Je l'utilise avec un objet formulaire, donc je ne suis pas sûr à 100% que cela fonctionne directement avec AR, mais cela devrait ...

6
Alex Ganov

Copiez le contenu de DirectUploadsController dans ActiveStorage dans le fichier app/controllers/active_storage/direct_uploads_controller.rb et modifiez la méthode create. Vous pouvez ajouter une authentification à ce contrôleur, ajouter des validations générales sur la taille du fichier ou le type mime, car la méthode create de ce contrôleur crée l'URL du fichier à télécharger. Vous pouvez donc empêcher tout téléchargement de fichier en contrôlant la taille et le type MIME dans ce contrôleur.

Une validation simple pourrait être:

# ...
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
Aref Aslani

J'ai trouvé un moyen de valider et de supprimer les pièces jointes avec callback before_save . C'est une approche utile car si vous validez le fichier pendant la transaction (et que vous souhaitez le purger), après avoir ajouté une erreur, la suppression de la pièce jointe sera annulée.

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
Adam Malinowski