Send_file with temporary files -- how to delete file after sending?

I’m looking for a way to stream temporary files and make sure they are
deleted after they are sent.

With Mongrel I can do something like this

Tempfile.open(‘ue-basket-’) do |zip|
Zip::ZipOutputStream.open(zip.path) do |zos|
items.each do |item|
zos.put_next_entry(item.filename)
zos.write(item.data)
end
end

send_file zip.path, :type => 'application/zip',
 :filename => item.filename

zip.unlink

end

By Unix filesystem semantics, zip.unlink does not free the blocks
(inodes) that make up the file. As long as there still is a reference to
it, the file still exists. However, the directory entry for the file is
deleted. The nice effect is that the file is no longer visible, but can
still be streamed. As soon as the last file descriptor referencing it is
closed, the file is finally deleted for good.

This doesn’t work anymore, when serving files is offloaded to the web-
server. The default Rails 3 (Rack-)middleware detects that a file is
being send (respond_to?(:to_path)), adds the file’s path as a special
header, which in turn is interpreted by the web server to serve that
particular file. Of course this can only work if the file is still
visible in the filesystem. Therefore the unlink trick doesn’t apply.

As a last resort, I can set up a cron job that removes temporary files
after they’ve reached a certain age. I’m still hoping for a more elegant
solution. Say, a hook that is executed after the server has finished
sending the file.

I’m using apache 2.2 and mod_xsendfile 0.9.

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/