在Rails中的send_file之后删除文件夹

时间:2012-11-12 22:24:18

标签: ruby-on-rails sendfile

我使用file.txt从我的Rails控制器发送文件send_file,然后删除包含它的文件夹。

send_file("#{Rails.root}/public/folder/file.txt")
FileUtils.remove_dir "#{Rails.root}/public/folder", true

当我这样做时,file.txt已被发送并删除。但是,folder未被删除。但是,如果我删除send_file行,则会删除folder

如何删除folder

编辑:有趣的是,我发现在folder内有一个名为.__afs2B0C的隐藏文件,可能会阻止删除。我不知道这个文件是如何创建的!该文件仅在大约15分钟后才会消失。

EDIT2:我尝试用vi检查临时文件的内容,但这是不可读的乱码。当我仅删除send_file行时,该文件夹已被正确删除。当我只删除FileUtils.remove_dir行时,该文件夹不包含临时文件。

5 个答案:

答案 0 :(得分:7)

您是否确定在删除目录时send_file仍未发送文件,如果它使用X-SendFile,它可能是异步的?这会在尝试删除目录时导致错误。

所以你应该排队这个删除操作,或者稍后用扫地机进行排队,而不是在将文件发送到流媒体后直接尝试。

我不清楚您要发送哪个文件,因此包含文件路径的实际示例,文件类型以及如何在您的问题中创建文件将非常有用。

可能有关调试的帮助:

执行以下操作时登录并监控文件夹:

  • 写出一个非常大的文件(大约60MB),并确认在文件创建过程中没有创建不可见的文件 - 我不清楚你实际发送的是哪个文件
  • 在慢速连接上设置大型文件传输,并监视此文件的创建和可能增长(例如,它可能与压缩文件中的文件有关)。

鉴于sendfile可能仍在通过Web服务器发送(对于大文件)(x-send-file现在是默认值),当您尝试删除时,我会尝试查看延迟解决方案。

可能的解决方案:

  • 使用send_data而不是send_file(如果文件很小)
  • 安排删除文件夹以便稍后使用delayed_job
  • 设置清扫工具,在每天结束时删除文件夹

答案 1 :(得分:1)

不确定为什么隐藏文件存在,它可能是X-send-file的分支,甚至是wget(部分进度或其他)的分支。

理想情况下,您应该使用Tempfile来执行此类操作。代码基于您对您正在做的事情的评论。另外,我使用两个宝石一个用于下载,另一个用于压缩。 这样,您根本不需要创建文件夹,只需要一个zip文件。 zip的所有内容文件将自行删除。下载zip后,只需将其删除即可。在这里我还要提一下,你可能会遇到一个小问题,因为send_file会将传输移交给网络服务器,因此你不会让rails进程在仍然被服务时删除文件。所以即使有这个,并且它在localhost上运行良好,我强烈建议在生产中使用自定义的预定背景垃圾收集器。

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

但是,这不应该是强制性的。如果你正在做没有Tempfiles的事情,请检查rails runner在目标目录上的权限。

FileUtils文档包含有关尝试删除文件/文件夹时本地安全漏洞的详细信息。

答案 2 :(得分:1)

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)

答案 3 :(得分:0)

答案 4 :(得分:-1)

它是如此简单但危险。使用shell命令来实现它。将其放在send_file

Controller之后
system ("rm -rf public/folder")