8

前段时间我写了一个关于在 Rails 应用程序中使用临时文件的问题。在特殊情况下,我决定使用tempfile

如果我还想使用该x-sendfile指令(作为 Rails 2 中的参数,或作为 Rails 3 中的配置选项),这会导致问题,以便文件发送由我的 Web 服务器直接处理,而不是我的 Rails 应用程序。

所以我想过做这样的事情:

require 'tempfile'

def foo()
  # creates a temporary file in tmp/
  Tempfile.open('prefix', "#{Rails.root}/tmp") do |f|
    f.print('a temp message')
    f.flush
    send_file(f.path, :x_sendfile => true) # send_file f.path in rails 3
  end
end

此设置有一个问题:文件在发送前被删除!

一方面,tempfile一旦Tempfile.open块结束就会删除文件。另一方面,x-sendfile使 send_file 调用异步 - 它返回非常快,因此服务器几乎没有时间发送文件。

我现在最好的解决方案是使用非临时文件(文件而不是临时文件),然后是一个定期擦除临时文件夹的 cron 任务。这有点不雅,因为:

  • 我必须使用自己的临时文件命名方案
  • 文件在 tmp 文件夹中停留的时间比需要的时间长。

有更好的设置吗?或者,在 asynchronous 上是否至少有一个“成功”回调send_file,所以我可以在完成后删除 f ?

非常感谢。

4

4 回答 4

2

鉴于 Rails3 在可用时使用 x-sendfile,并且无法停用它,因此您不能将 send_file 与诸如 TempFile 之类的库一起使用。最好的选择是我在问题中提到的那个:使用常规文件,并有一个定期删除旧临时文件的 cron 任务。

编辑:删除未使用的文件现在更容易使用 maid gem 处理:

https://github.com/benjaminoakes/maid

于 2012-07-13T21:03:33.370 回答
0

不要将 send_file 放在块中。

f = Tempfile.new('prefix', "#{Rails.root}/tmp")
f.print('a temp message')
f.close
send_file(f.path, :x-sendfile => true)

然后使用另一个脚本清理临时文件

于 2011-05-18T12:04:24.373 回答
0

文件临时 gem 怎么样?https://github.com/djberg96/file-temp

require 'file/temp'

fh = File::Temp.new(false)
fh.puts "world"
fh.close # => Tempfile still on your filesystem

就像 zzzhc 的回答一样,您需要在外部管理清理

于 2011-05-24T18:46:14.793 回答
0

您可以取消定义 Tempfile 实例的终结器,以便在实例被销毁时永远不会删除您的文件,然后让 chron 任务处理它。

require 'tempfile'

def foo()
  # creates a temporary file in tmp/
  Tempfile.open('prefix', "#{Rails.root}/tmp") do |f|
    f.print('a temp message')
    f.flush
    ObjectSpace.undefine_finalizer(f) # 'disables' deletion when GC'ed
    send_file(f.path, :x_sendfile => true) # send_file f.path in rails 3
 end
end
于 2013-09-27T08:22:49.417 回答