Reputation: 52648
Some time ago I wrote a question regarding the use of temporary files within a rails app. On thar particular case, I decided to use tempfile
This causes a problem if I also want to use the x-sendfile
directive (as a parameter in Rails 2, or as a configuration option in Rails 3) so that the file sending is handled by my web server directly, not my rails app.
So I thought about doing something like this:
require 'tempfile'
def foo()
# creates a temporary file in tmp/
Tempfile.open('prefix', "#{Rails.root}/tmp") do |f|
f.print('a temp message')
f.flush
send_file(f.path, :x_sendfile => true) # send_file f.path in rails 3
end
end
This setup has one issue: the file is deleted before being sent!
On one hand, tempfile
will delete the file as soon as the Tempfile.open
block is over. On the other, x-sendfile
makes the send_file call asynchronous - it returns very quickly, so the server hardly has time to send the file.
My best possible solution right now involves using non-temporary files (File instead of Tempfile), and then a cron task that erases the temp folder periodically. This is a bit inelegant since:
Is there a better setup? Or, is there at least a "success" callback on the asynchronous send_file
, so I can erase f when it's done?
Thanks a lot.
Upvotes: 8
Views: 5441
Reputation: 2617
You can undefine Tempfile instance's finalizer so that your file never gets deleted when the instance is detroyed and then let the chron task handle it.
require 'tempfile'
def foo()
# creates a temporary file in tmp/
Tempfile.open('prefix', "#{Rails.root}/tmp") do |f|
f.print('a temp message')
f.flush
ObjectSpace.undefine_finalizer(f) # 'disables' deletion when GC'ed
send_file(f.path, :x_sendfile => true) # send_file f.path in rails 3
end
end
Upvotes: 0
Reputation: 52648
Given that Rails3 uses x-sendfile when it is available, and there is no way to deactivate it, you just can't use send_file with a library such as TempFile. The best option is the one I mentioned in the question: use a regular File, and have a cron task that removes old temp files periodically.
EDIT: The removal of unused files has now been easier to deal with with the maid gem:
https://github.com/benjaminoakes/maid
Upvotes: 2
Reputation: 69
How about the file-temp gem? https://github.com/djberg96/file-temp
require 'file/temp'
fh = File::Temp.new(false)
fh.puts "world"
fh.close # => Tempfile still on your filesystem
Like the zzzhc's answer, you would need to manage cleanup externally
Upvotes: 0
Reputation: 395
don't put send_file in block.
f = Tempfile.new('prefix', "#{Rails.root}/tmp")
f.print('a temp message')
f.close
send_file(f.path, :x-sendfile => true)
then using another script to cleanup tempfile
Upvotes: 0