thoughtbot / paperclip

Easy file attachment management for ActiveRecord
https://thoughtbot.com
Other
9.01k stars 2.43k forks source link

Uploaded files with the same filename causes error in production #719

Closed mobits closed 12 years ago

mobits commented 12 years ago

Hi,

suppose I upload an attachment with name "foo.txt" and later upload a different file but with the same name. In production, (i.e. with config.cache_classes = true), if I request the attachment, it will provide me the old file content!

Here is the scenario:

my model class

class Bar < ActiveRecord::Base

  has_attached_file :my_attachment

end

in development.rb (in order to reproduce the error)

...
  config.cache_classes = true
...

I know I could "solve" this problem forcing :path value to include something like :fingerprint, but I believe the problem above is a bug.

jyurek commented 12 years ago

I'm not exactly sure what you mean here. If you upload foo.txt once, then, say, 5 minutes later, upload a different foo.txt to the same model, it doesn't change? What do you mean what you "request the attachment"? With the attachment definition as you have it, it would store it on the filesystem, so requesting it through the browser would read the new file off the disk. If that's the case, I think it's more of an apache/nginx problem, isn't it? Are you using timestamped URLs to request the file?

mobits commented 12 years ago

I created a rails project just to verify this error. You can find the relevant snippets of code at this gist: https://gist.github.com/1689722

Basically its a project where you can create maps and upload kml files with the map data so one can display it on Google Maps for instance.

At the gist, you'll find two kml files as example (must rename them with the same filename to cause the error).

If we change the map source and call /maps/1.kml then the old content is provided.

When I first noticed this error, I thought it was something wrong about Apache too, but I realized that if I just set config.cache_classes = true in development environment (no Apache, just Webrick) the bug happened the same way.

I believe the problem could be here: format.kml { render :file => @map.source.path } What do you think?

sikachu commented 12 years ago

Yeah, I think it's actually caching your output. You might want to try using send_file or send_data (by reading data) here: http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_data

(I found some similar issue here: http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/05ef121d358756fe?pli=1)

jyurek commented 12 years ago

So to expand on this a little. @mobits, you don't specify anything on your attachment definition, and that means it's going to be loaded off the filesystem. If that happens, it's your HTTP server's problem (apache or nginx if remote; thin, mongrel, webrick, or so on if local). However, I think if you're running an appserver locally, static file requests still go through Rails, which would mean that it can cache aggressively, especially with cache_classes on.

So, the problem is that you're loading file locally with cache_classes when that situation wouldn't ever happen on a server (unless you exposed your app server directly, which is never a good idea).

mobits commented 12 years ago

I believe I just misused render :file like @sikachu said. Probably this method was not meant to render files that could be changed by user action, but to render html or other templates that should only be changed in development stage.

That's probably why Rails caches it in production environment like any classes or other resources. Living and learning :)