Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Empty file uploads should not come through as empty Tempfiles

#1785

We're using Paperclip for file uploads and recent edge Rails rendered our user profile forms unusable.

File uploads don't break our application when there was an actual file upload; what breaks Paperclip is the case when nothing was selected in the file input. The form is still sent with multipart encoding and parsed by Rack, which creates a Tempfile regardless of whether some data was received or not.

The result of Rack processing a single file field is a hash with these keys: {:filename, :type, :name, :tempfile, :head}.

Rails further processes this in ActionController::UrlEncodedPairParser.get_typed_value. When it sees the above formatted hash, it replaces it with the Tempfile object it references and applies other metadata, like filename, as properties of this object.

In short, when a "user[avatar]" file field was sent empty, older Rails version would receive nothing:


params[:user][:avatar]  # => nil

Now a Tempfile is received in any case:


params[:user][:avatar]  # => #<File:/tmp/RackMultipart.xxxyyy>

So naturally Paperclip thinks a file was uploaded and explodes because this object has nil value original_filename and a size of 0.

A solution is to check for Tempfile size and not let it through if it's zero.

Reported by Mislav · January 20th, 2009 @ 05:18 PM

State: resolved
Milestone: none
Assigned to: josh josh
Importance: none

Activity

  1. josh
    josh
    • Milestone cleared.
    • State changed from new to open
    • Assigned user set to josh

    January 20th, 2009 @ 05:31 PM

  2. Xavier Noria
    Xavier Noria

    An uploaded file could have size 0... Wouldn't be possible to test something else like value[:filename].nil? ?

    Not really into it so don't know if it is a valid alternative indeed.

    January 20th, 2009 @ 05:53 PM

  3. Mislav
    Mislav
    • Assigned user cleared.

    Theoretically it could, but what good is storing a 0-byte file? I say ignore it

    January 20th, 2009 @ 06:38 PM

  4. Repository
    Repository
    • State changed from open to resolved

    (from [01f06fc7f4dda52035d5a2273d402d8555a897a5]) Don't let empty Tempfiles come through as uploaded files [#1785 state:resolved]

    Signed-off-by: Joshua Peek josh@joshpeek.com http://github.com/rails/rails/co...

    January 20th, 2009 @ 06:40 PM

  5. Xavier Noria
    Xavier Noria

    I think it doesn't matter if you cannot come up with a use case if you can be correct by the same price.

    The patch should test whether a file was uploaded, and it doesn't test that. That's my point. If it could it should.

    January 20th, 2009 @ 06:45 PM

  6. josh
    josh
    • Assigned user set to josh

    I created the test fixture by dumping the raw POST body from an empty file upload in Safari.

    http://github.com/rails/rails/bl...

    Am I missing something else?

    January 20th, 2009 @ 08:49 PM

  7. Mislav
    Mislav

    Xavier, would you say that this is a better test for when a file was not uploaded?

    
    if value.has_key?(:tempfile) and
      not (value[:tempfile].size == 0 and value[:filename].blank?)
    

    This check allows 0-sized files to be uploaded if they have a filename.

    January 20th, 2009 @ 10:54 PM

  8. josh
    josh
    • State changed from resolved to open

    Now I'm confused? Xavier, I guess you were referring the to test conditional not test fixture :)

    After some more testing, it seems like we could just check for value[:filename].blank? This always seems to be the case when the user does not select a file. This should allow users to upload a text file with no contents.

    January 21st, 2009 @ 12:05 AM

  9. josh
  10. Xavier Noria
    Xavier Noria

    Exactly, my untested guess is that to test if the file was uploaded you just check value[:filename].blank?.

    If that's correct checking the size would not be necessary.

    January 21st, 2009 @ 12:33 AM

  11. josh
    josh
    • State changed from open to resolved

    I think this is the fix we wanted

    http://github.com/rails/rails/co...

    January 21st, 2009 @ 02:36 AM

  12. MatthewRudy
    MatthewRudy

    Great

    Thanks.

    I hit this problem on Monday, but didn't have time to debug it.

    Nice one.

    January 21st, 2009 @ 10:14 AM

  13. Thijs
    Thijs

    I'm stil seeing the first reported behaviour with Paperclip master and Rails master. Am I missing something?

    February 14th, 2009 @ 05:11 PM

  14. Mislav
    Mislav

    I didn't experience it anymore after the fix.

    The best bet is to test this in your browser: submit a form with empty file field and inspect the parameters you've got in the controller. Is it a Tempfile? If so, can you inspect its properties like original_filename and size?

    February 15th, 2009 @ 11:46 AM