Question

I have a Redmine plugin. I create a temporary file in /tmp, then I send it with File.open. I want to delete the temporary file when user has download it. How can I do ?

My code (in a controller):

File.open(filelocation, 'r') do |file|
  send_file file, :filename => filename, :type => "application/pdf", :disposition => "attachment"
end

If I remove the file after File.open, it doesn't work.

EDIT

In my controller I do:

def something
  temp = Tempfile.new(['PDF_','.pdf'])
  # ... some code that modify my pdf ...

  begin
    File.open(temp.path, 'r') do |file|
      send_file file, :filename => temp.path, :type => "application/pdf", :disposition => "attachment"
    end

  ensure
    temp.close
    temp.unlink
  end

end

My temporary file is remove, but not in the end of my code: the File.open return a damage PDF.

Was it helpful?

Solution

I use send_data instead of send_file, then I delete the file. send_data will block until the data is sent, allowing File.delete request to succeed.

 file = temp.path
 File.open(file, 'r') do |f|
   send_data f.read.force_encoding('BINARY'), :filename => filename, :type => "application/pdf", :disposition => "attachment"
 end
 File.delete(file)

source: In Ruby on Rails, After send_file method delete the file from server

OTHER TIPS

Call send_file can be offloaded to a web server, therefore it can return asynchronously. Doing anything in tempfile block is dangerous as well as trying to close and unlink the file. When using send_file, the only option is to give up on cleaning the temporary files within the web process.

Consider using the Tempfile class for your job:

Tempfile.create('foo', '/tmp') do |f|
   ... do something with f ...
end

It's included in standard library and cleanup occur automatically when the block is closed.

Reference: http://www.ruby-doc.org/stdlib-2.1.1/libdoc/tempfile/rdoc/index.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top