将远程文件流式传输到ruby / rails 4 / unicorn / nginx中的客户端

时间:2016-04-15 10:45:53

标签: ruby-on-rails ruby nginx streaming unicorn

我正在尝试使用Ruby on Rails 4.2将文件从远程存储服务(不是s3 :-))流式传输到客户端。

我的服务器需要处于中间状态以验证客户端请求,但也需要建立对远程存储服务的请求,因为对该服务的所有请求都需要使用自定义标头参数进行身份验证。这使得不可能做一个简单的redirect_to并让客户端直接下载文件(但是如果这实际上可以使用rails,请告诉我!)。此外,我想保留文件的网址为客户端隐藏。

到目前为止,我正在使用名为ZipLine的gem,但这也无法正常工作,因为它仍会在将远程文件发送到客户端之前对其进行缓冲。因为我正在使用unicorn / nginx,这可能也是由于这两个中的任何一个设置阻止了正确的流式传输。

根据rails doc的说明,我尝试添加

listen 3000, tcp_nopush: false

配置/ unicorn.rb但无济于事。

解决方案可能是在本地缓存远程文件一段时间,然后只提供该文件。这会使一些事情变得更容易,但也会产生新的麻烦,例如保持远程和缓存文件同步,为缓存过期设置正确的触发器等。

总结一下:

1)如何完成上述方案?

2)如果这不是一种智能/高效的做事方式,我应该只缓存远程副本吗?

3)在给定方案中,您的经验/建议是什么?

我遇到了散布在互联网周围的各种解决方案,但没有一个能激发出完整的解决方案。

谢谢!

1 个答案:

答案 0 :(得分:1)

我假设第三方存储服务具有HTTP访问权限。如果你考虑使用redirect_to,我认为该服务还提供了允许每个下载授权的方法。与标头中的唯一键一样,过期并且不会将过期时间作为参数暴露给您的秘密api密钥或HMAC签名URL。

无论如何,大多数云存储服务都提供这种文件访问。我强烈建议让服务流传输文件。您的应用应该只是授权用户并重定向到该服务。 Rails允许您在重定向时添加自定义标头。它在Rails guides中进行了讨论。

  

10.2.1设置自定义标题

     

如果要为响应设置自定义标头,请选择response.headers   是去做的地方。 headers属性是映射的哈希   标题名称为其值,Rails将设置其中的一些   自动。如果要添加或更改标题,只需指定它即可   到response.headers

所以你的行动代码最终会是这样的:

def download
  # do_auth_check

  response.headers["Your-API-Auth-Key"] = "SOME-RANDOM-STRING"
  redirect_to url
end

不要通过流式传输所有这些下载来消耗不必要的服务器资源。毕竟我们正在支付云服务:)