I'm sending the file file.txt
from my Rails controller using send_file
, and then delete the folder containing it.
send_file("#{Rails.root}/public/folder/file.txt")
FileUtils.remove_dir "#{Rails.root}/public/folder", true
When I did this, file.txt
was sent and deleted. However, folder
was not deleted. But if I remove the send_file
line, then folder
will be deleted.
How do I make it delete folder
?
EDIT: Interestingly, I found that inside folder
there is a hidden file called .__afs2B0C
, probably preventing the deletion. I have no idea how this file is created! The file stays for only around 15 minutes before disappearing.
EDIT2: I've tried inspecting the content of the temp file with vi
, but it's unreadable gibberish. When I removed only the send_file
line, the folder was correctly deleted. When I removed only the FileUtils.remove_dir
line, the folder contains no temp file.
Are you sure the send_file is not still sending the file when you are removing the dir, it may be asynchronous if it uses X-SendFile? That would cause an error when trying to remove the dir.
So you should probably be queuing this delete action, or doing it with a sweeper later, rather than trying to do it straight after sending the file to streaming.
I'm not completely clear on which file you are sending, so it would be useful to include an actual example of file path, and file type, and how it is created in your question.
Possible help with debugging:
Log in and monitor the folder while you perform the following actions:
Given that sendfile may still be sending (for large files) via the web server (x-send-file is now default) when you try to delete, I'd try looking into delayed solutions.
Possible solutions:
Not sure why that hidden file is there, it could be an offshoot of X-send-file or even of wget (partial progress or something).
Ideally, you should use Tempfile to do things like this. The code is based of you're comment about what you are doing. Also, I am using two gems one for downloading and another for zipping. This way, you don't need to make a folder at all, just a zip file directly. All the content files of the zip will be deleted on their own. After downloading the zip just delete it. Here also I should mention that you could run into a glitch somewhere, since the send_file will hand over the transfer to the webserver, and as such you don't the rails process to delete the file while it is still being served. So even with this, and it working well on localhost, I would strongly advise using a custom scheduled background garbage collector in production.
require 'open-uri'
require 'zip/zip'
zip_path = "#{Rails.root}/public/test.zip"
urls_to_fetch = ['abc.com', 'xyz.com']
Zip::ZipFile.open(zip_path, Zip::ZipFile::CREATE) do |zipfile|
urls_to_fetch.each_with_index do |url, index|
# intialize new temp file
file = Tempfile.new(index.to_s)
# fetch the file using open-uri or wget and save it as a tmpfile
open(url, 'rb') do |read_file|
file.write(read_file.read)
end
end
# add the temp file to the list of files to zip
zipfile.add(File.basename(file), file.path)
end
# send the zipfile for download
send_file zip_path
# delete the zipfile
FileUtils.rm zip_path
However, this should not be mandatory. If you are doing things without Tempfiles, please check the rights that the rails runner has on the target directory.
The FileUtils documentation has details regarding local security vulnerabilities when trying to delete files / folders.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With