Rails - x-sendfile +临时文件

发布于 2024-11-07 19:40:43 字数 1210 浏览 7 评论 0原文

不久前,我写了一个问题关于在 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.open 块结束,tempfile 就会删除该文件。另一方面,x-sendfile 使 send_file 调用异步 - 它返回得非常快,因此服务器几乎没有时间发送文件。

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

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

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

多谢。

Some time ago I wrote a question regarding the use of temporary files within a rails app. On thar particular case, I decided to use tempfile

This causes a problem if I also want to use the x-sendfile directive (as a parameter in Rails 2, or as a configuration option in Rails 3) so that the file sending is handled by my web server directly, not my rails app.

So I thought about doing something like this:

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

This setup has one issue: the file is deleted before being sent!

On one hand, tempfile will delete the file as soon as the Tempfile.open block is over. On the other, x-sendfile makes the send_file call asynchronous - it returns very quickly, so the server hardly has time to send the file.

My best possible solution right now involves using non-temporary files (File instead of Tempfile), and then a cron task that erases the temp folder periodically. This is a bit inelegant since:

  • I have to use my own tempfile naming scheme
  • Files stay on the tmp folder longer than they are needed.

Is there a better setup? Or, is there at least a "success" callback on the asynchronous send_file, so I can erase f when it's done?

Thanks a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

又怨 2024-11-14 19:40:43

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

编辑:现在使用 maid gem 可以更轻松地处理未使用的文件的删除:

https://github.com/本杰米诺克斯/女仆

Given that Rails3 uses x-sendfile when it is available, and there is no way to deactivate it, you just can't use send_file with a library such as TempFile. The best option is the one I mentioned in the question: use a regular File, and have a cron task that removes old temp files periodically.

EDIT: The removal of unused files has now been easier to deal with with the maid gem:

https://github.com/benjaminoakes/maid

像你 2024-11-14 19:40:43

不要将 send_file 放入块中。

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

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

don't put send_file in block.

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

then using another script to cleanup tempfile

谈下烟灰 2024-11-14 19:40:43

file-temp 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的答案一样,你需要管理外部清理

How about the file-temp 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

Like the zzzhc's answer, you would need to manage cleanup externally

囚我心虐我身 2024-11-14 19:40:43

您可以取消定义 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

You can undefine Tempfile instance's finalizer so that your file never gets deleted when the instance is detroyed and then let the chron task handle it.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文