Ruby on Rails中,send_data和send_file有什么区别?

88

哪种方法最适合流媒体和文件下载?

请提供示例。

2个回答

124
send_data(_data_, options = {})
send_file(_path_, options = {}) 

主要的区别在于你可以使用 send_data 传递数据(二进制代码或其他)或使用 send_file 传递文件路径。

因此,你可以生成一些数据并将其作为内联文本或附件发送,而无需通过 send_data 在你的服务器上生成文件。或者你可以使用 send_file 发送准备好的文件。

data = "Hello World!"
send_data( data, :filename => "my_file.txt" )

或者

data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_file( file )

为了提高性能,最好生成文件一次,然后根据需要多次发送。因此,send_file 更合适。

就流传输而言,据我所知,这两种方法使用相同的一组选项和设置,因此您可以使用 X-Send 或其他方法。

更新

发送数据并保存文件:

data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_data( data )

1
谢谢@fl00r。是否有办法将数据保存为文件,然后使用send_data函数发送?因为我需要服务器上的文件副本。我应该怎么做? - Mr. Black
你的代码有错误:应该是 { |f| f << data } - True Soft
您好,我想知道这个答案是否仍然相关?我现在正在使用Rails 3.2.16,并且使用send_file时我必须使用文件本身而不是路径才能使它工作。只是想更新一下,以防其他人遇到此类情况。 - FireDragon

24

send_file 可能比 send_data 更快。

正如 fl00r提到的那样send_file 使用文件路径,send_data 使用数据。

因此,send_filesend_data 的子集,因为它需要在文件系统上有一个文件:当然,你可以只读取文件并在其上使用 send_data 。但是,send_file 可能更快,因此这是性能/通用性权衡。

因为send_file 知道文件路径,所以它可以在Apache(X-Accel-Redirect Nginx)上发送 X-Sendfile 头而不是文件内容。

反向代理(Apache或Nginx)消耗此标头,通常在运行Rails的生产设置之前。

如果响应中存在X-Sendfile,则反向代理会忽略大部分当前响应,并构建一个新响应以返回给定路径的文件。

Client <---> Internet <---> Reverse proxy <---> Rails

由于反向代理服务器非常擅长提供静态文件服务,因此这种方法更加高效,比Rails快得多(如果将发送X-Sendfile,则不会发送文件数据)。

send_file的典型用例是当您想要控制静态文件的访问权限时:您不能将它们放在/public下,否则它们将在Rails有机会进行决策之前被服务。这在以下页面上有所讨论:Protecting the content of public/ in a Rails app

为了使用X-Sendfile头,您需要添加:

config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx

请将代码添加到 config/initializers/production.rb(或者在Rails 5.x中是config/environment/production.rb),而不是application.rb,因为在开发中您没有代理服务器并希望send_file实际上发送数据。

X-SendfileAsset Pipeline Guide中讨论。


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