How to Fake an Uploaded File

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!