Delete folder after send_file in Rails

I send the file.txt file 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, the folder not been deleted. But if I delete the send_file line, then the folder will be deleted.

How do I delete its folder ?

EDIT: Interestingly, I found that there is a hidden file inside the folder named .__afs2B0C , possibly preventing deletion. I do not know how this file is created! The file remains only about 15 minutes before disappearing.

EDIT2: I tried to check the contents of the temporary file with vi , but this is unreadable gibberish. When I deleted only the send_file line, the folder was deleted correctly. When I deleted only the line FileUtils.remove_dir , the folder does not contain a temporary file.

+4
source share
5 answers

Are you sure that the send_file file still does not send the file when the directory is deleted, can it be asynchronous if it uses the X-SendFile? This will result in an error when trying to delete a directory.

Therefore, you should probably be in the queue for this deletion action or do it later with the sweeper instead of trying to do it right after sending the file to the stream.

I don’t quite understand which file you are sending, so it would be useful to include an actual example of the file path and file type and how it is created in your question.

Possible debugging help:

Log in and view the folder while doing the following:

  • Write a very large file (say 60 MB) and check if there is an invisible file created during the file creation process. I do not know which file you are actually sending.
  • Set up a large file transfer on a slow connection and watch for the creation and, possibly, extension of this file (this may be due to the compression of a file that runs on the fly, for example).

Given that sendfile can still send (for large files) via the web server (x-send-file is now the default), when you try to delete, I would try to find pending solutions.

Possible solutions:

  • Use send_data, not send_file (if the files are small)
  • Plan on deleting the folder later with something like delayed_job
  • Set up a sweeper that removes folders at the end of each day.
+7
source

Not sure why this hidden file exists, it could be a branch of the X-send file or even wget (partial progress or something else).

Ideally, you should use a Tempfile to do this. The code is based on a comment about what you are doing. In addition, I use two gems, one for loading and the other for fastening. This way you do not need to create a folder at all, just a zip file directly. All zip content files will be deleted on their own. After downloading zip, just uninstall it. Here I should also mention that you may encounter a glitch somewhere, since send_file will transfer the transmission to the web server, and as such you do not handle rails to delete the file while it is still being served. So even with this, and it works well on the local host, I would strongly advise using a special garbage collector to collect data 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 required. If you are doing something without Tempfiles, check the permissions that the rails runner has in the target directory.

The FileUtils documentation contains information about local security vulnerabilities when trying to delete files / folders.

+1
source

See here ... works for me

  file = File.open(Rails.root.join('public', 'uploads', filename), "rb") contents = file.read file.close File.delete(filepath) if File.exist?(filepath) send_data(contents, :filename => filename) 
+1
source

It is so simple but dangerous. Use the shell command to achieve it. Put it after send_file in Controller

 system ("rm -rf public/folder") 
-1
source

Source: https://habr.com/ru/post/1445637/


All Articles