在不存储附件的情况下使用回形针验证

Use Paperclip validations without storing the attachment

我正在构建一个 Rails 端点来代理不同的服务并映射来自所述服务的响应。主要问题是将文件附件的字节数据传递给该服务。

一个限制是我必须在传递文件之前对文件进行一些健全性检查。

我不需要将文件保存在我的 Rails 应用程序中,它仅用作其他服务的输入。

在一个非常简单的实现中,我只是从包装在 Tempfile 中的适当请求参数中读取字节,但这当然不需要完整性检查,因此还不够好。

我对执行 Paperclip 支持的验证类型很感兴趣,尤其是大小和内容类型,但我不想将实际文件存储在任何地方。

是否可以仅使用 Paperclip 的验证部分而不将附件存储在任何地方?

您可以使用 gem ruby-filemagic 验证文件 mime 类型:

FileMagic.new(FileMagic::MAGIC_MIME).file(your_tempfile.path) #=> "image/png; charset=binary"

您可以通过 your_tempfile.size

查看尺码

这就是我最终解决它的方式,深受 https://gist.github.com/basgys/5712426

的启发

因为我的项目已经在使用 Paperclip,所以我寻求基于它的解决方案,而不是包含更多的 gem。

首先,一个像这样的非持久化模型:

class Thumbnail
  extend ActiveModel::Callbacks
  include ActiveModel::Model
  include Paperclip::Glue

  ALLOWED_SIZE_RANGE = 1..1500.kilobytes.freeze
  ALLOWED_CONTENT = ['image/jpeg'].freeze

  # Paperclip required callbacks
  define_model_callbacks :save, only: [:after]
  define_model_callbacks :destroy, only: %i(before after)

  attr_accessor :image_file_name,
                :image_content_type,
                :image_file_size,
                :image_updated_at,
                :id

  has_attached_file :image
  validates_attachment :image,
                       presence: true,
                       content_type: { content_type: ALLOWED_CONTENT },
                       size: { in: ALLOWED_SIZE_RANGE }

  def errors
    @errors ||= ActiveModel::Errors.new(self)
  end
end

然后,将来自控制器的传入图像文件包装在该模型中:

class SomeController < ApplicationController
  before_action :validate_thumbnail

  def some_action
    some_service.send(image_data)
  end


  private

  def thumbnail
    @thumbnail ||= Thumbnail.new(image: params.require(:image))
  end    

  def validate_thumbnail
    render_errors model: thumbnail if thumbnail.invalid?
  end

  def image_data
    Paperclip.io_adapters.for(thumbnail.image).read
  end

  def some_service
    # memoized service instance here
  end   
end