Our store software contains an extensive set of routines for processing uploaded images and resizing them into various image sizes. We’ve recently been adding some code to support a bulk import function and it’s become necessary to somehow fake uploading a file, given a specific URL for an image.
The basic plan is to use Net::HTTP to connect to the remote server and grab the image and save it in a temporary file. It turns out that Rails contains a UploadedTempfile class which is a subclass of Tempfile, and this is used by the CGI routines to handle any uploaded files.
So all we need to do is create our own instance of UploadedTempfile, set some attributes and then pass it along to our existing routines as if it were a real uploaded file.
uri = URI.parse(image_url)
image_file_name = File.basename(uri.path) # Extract the file name
image_file = nil
begin
timeout(10) do
Net::HTTP.start(uri.host, uri.port) do |http|
resp = http.get(uri.path)
image_file = ActionController::UploadedTempfile.new(image_file_name)
image_file.binmode
image_file.write(resp.body)
image_file.original_path = image_file_name
image_file.rewind
end
end
rescue TimeoutError
raise "Timeout connecting to #{uri.host}"
end
There are a few things that need to be set up, so that the fake upload file works properly.
The file is set to binary mode with
image_file.binmode
The original file name is set with
image_file.original_path = image_file_name
A content type attribute can also be set with
image_file.content_type
but we don’t use this attribute, so it’s not set here.
Finally we rewind the file so that we can read it later on in the image processing routines. When we’re finished with the temporary file, we can delete it with a
image_file.close!