当通过send_file在Sinatra发送文件后,我该如何删除文件?

12
我有一个简单的Sinatra应用程序,需要通过外部进程生成一个文件,将该文件发送到浏览器,最后从文件系统中删除该文件。 大致如下:
class MyApp < Sinatra::Base
  get '/generate-file' do

    # calls out to an external process, 
    # and returns the path to the generated file
    file_path = generate_the_file()  

    # send the file to the browser
    send_file(file_path)

    # remove the generated file, so we don't
    # completely fill up the filesystem.
    File.delete(file_path)

    # File.delete is never called.

  end
end

然而,似乎send_file调用会完成请求,并且其后的任何代码都不会运行。

是否有某种方法确保生成的文件在成功发送到浏览器后被清除?或者我需要使用cron作业定期运行清理脚本?

3个回答

3

很遗憾,使用send_file时没有任何回调函数。在这里的常见解决方案是使用cron任务来清理临时文件。


我晚了10年,但你能否用Ruby编写一个cron任务示例来完成这个任务?还是有别的方法? - crodev

1

send_file函数是流式传输文件,它不是同步调用,因此您可能无法捕获其结束并清理文件。我建议将其用于静态文件或非常大的文件。对于大文件,您需要一个cron job或其他解决方案以后清理。您不能在同一方法中执行此操作,因为send_file函数在get方法仍在执行时不会终止。如果您不关心流式传输部分,则可以使用同步选项。

begin
   file_path = generate_the_file()  
   result File.read(file_path)
   #...
   result # This is the return
ensure
   File.delete(file_path) # This will be called..
end

当然,如果您没有对文件进行任何高级操作,您可以使用Jochem的答案,完全省略begin-ensure-end。

1

这可能是一个解决方案,将文件内容暂时存储在变量中,例如:

contents = file.read

之后,删除该文件:

File.delete(file_path)

最后,返回内容:

内容

这与您的send_file()具有相同的效果。


这样会不会使用更多的内存? - James
@Kira,向浏览器发送4GB的文件?在generate_the_file()方法中应该防止这种情况发生。我的建议是改变操作顺序,使得在浏览器接收文件之前先删除生成的文件...原问题。 - Jochem Schulenklopper
@James,这可能会有一些问题(虚拟机在中间结果的内存使用方面可能会很聪明)。但它解决了原始请求中的问题... - Jochem Schulenklopper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接