【问题标题】:How can I delete a file in Sinatra after it has been sent via send_file?通过 send_file 发送文件后,如何在 Sinatra 中删除文件?
【发布时间】:2021-01-26 17:05:34
【问题描述】:

我有一个简单的 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 作业?

【问题讨论】:

    标签: ruby sinatra


    【解决方案1】:

    不幸的是,当您使用 send_file 时没有任何回调。这里常见的解决方案是使用 cron 任务来清理临时文件

    【讨论】:

    • 我迟到了 10 年,但你能不能用 ruby​​ 写一个 cron 任务示例来做到这一点?或者用什么?
    【解决方案2】:

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

    contents = file.read

    之后,删除文件:

    File.delete(file_path)

    最后,返回内容:

    内容

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

    【讨论】:

    • 这不会占用更多内存吗?
    • @Kira,向浏览器发送 4GB 文件?在generate_the_file() 方法中应该防止这种情况。我的建议是更改操作顺序,以便在浏览器接收文件之前删除生成的文件......原来的问题。
    • @James,它可能...(尽管虚拟机在中间结果的内存使用方面可能很聪明)。但它解决了原始请求中的问题......
    【解决方案3】:

    send_file 正在流式传输文件,它不是同步调用,因此您可能无法捕捉到它的结尾来清理文件。我建议将它用于静态文件或非常大的文件。对于大文件,您将需要一个 cron 作业或其他一些解决方案来稍后进行清理。您不能使用相同的方法执行此操作,因为 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。

    【讨论】:

      猜你喜欢
      • 2022-12-21
      • 1970-01-01
      • 2012-11-01
      • 2019-05-13
      • 2013-03-03
      • 2021-12-24
      • 1970-01-01
      • 2013-07-29
      • 2012-10-23
      相关资源
      最近更新 更多