Reputation: 2014
I am building a Rails endpoint that proxies a different service and maps the responses from said service. The main problem is to pass along a file attachment's byte data to that service.
A constraint is that I must do some sanity checks on the file before I pass it along.
I have no need to persist the file in my Rails app, it is merely used as input to the other service.
In a very simple implementation I simply just read the bytes from the appropriate request parameter which is wrapped in a Tempfile
, but this of course entails no sanity checks, and therefore is not good enough.
I am interested in doing the kinds of validation that Paperclip supports, in particular size and content type, but I would prefer to not store the actual file anywhere.
Is it possible to use only the validation parts of Paperclip and not store the attachment anywhere?
Upvotes: 1
Views: 283
Reputation: 2014
This is how I ended up solving it, heavily inspired by https://gist.github.com/basgys/5712426
Since my project was already using Paperclip, I went for a solution based on that rather than including more gems.
First, a non-persisted model like so:
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
Then, wrap the incoming image file in that model from the controller:
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
Upvotes: 2
Reputation: 1771
You can verify the file mime-type with the gem ruby-filemagic :
FileMagic.new(FileMagic::MAGIC_MIME).file(your_tempfile.path) #=> "image/png; charset=binary"
For the size you could just check with your_tempfile.size
Upvotes: 1