Post History:

Animals Matter to Me

The three faces of uploaded files in Rails

When using a file_field to upload files to a Rails app, the parameter containing the uploaded file can be one of three possible classes:

  • If a user submits the form without selecting a file for the upload input field, the parameter will be an empty String.
  • If the uploaded file is small, less than about 20 KB, the parameter will be an instance of ActionController::UploadedStringIO.
  • If the file is larger, it will be saved as a temporary file and the parameter will be an instance of ActionController::UploadedTempfile.

It is possible to deal with objects of all three types without explicitly checking the class of the parameter. All three will respond to blank? but only the empty string (no file selected) will return true. Note that a zero length file will return false to blank?. Both types of file data have read and size methods and they do what one would expect.

One method to use with care is local_path. Although both uploaded data types respond to it, UploadedTempfile will return the path to the temporary file created on the server, and UploadedStringIO will return nil because no file was created in the filesystem. Some code that was incorrectly relying on a local_path being present caused the problem I encountered at work which made me aware of this issue.

Another way to deal with this is to let a plugin handle it. Plugins like attachment_fu deal with the different classes as part of their normal handling of uploaded files.

The solution for the particular piece of code we were dealing with was to change from attempting to explicitly open a temp file to using the blank? and read methods to get the uploaded data, regardless of type.


Adding new comments is currently disabled.