Rails:如何将文件从S3发送到远程服务器

我一直在打猎,似乎无法找到一个好的解决方案。 My Rails应用程序将其文件存储在Amazon S3中。 我现在需要将它们发送到远程(第三方)服务。

我正在使用RestClient发布到第三方服务器,如下所示:

send_file = RestClient::Request.execute( :method => :post, :url => "http://remote-server-url.com", :payload => File.new("some_local_file.avi", 'rb'), :multipart => true, etc.... ) 

它适用于本地文件,但如何将S3中的远程文件直接发送到此第三方服务?

我在这里找到了一个答案,其中有人使用open-uri: ruby从S3读取带有open-URI的文件

我为自己测试了它,并且它有效。

 :payload => open(URI.parse("http://amazon-s3-example.com/some_file.avi")) 

但是,我在这里读到一条评论说open-uri只是将远程文件加载到内存中。 请参阅此答案的最新评论: https : //stackoverflow.com/a/264239/2785592

这不太理想,因为我正在处理潜在的大型video文件。 我还读过RestClient甚至将本地文件加载到内存中的某个地方; 再次,这不是理想的。 有谁知道这是真的吗?

当然,我不能成为唯一有这个问题的人。 我知道我可以在发送之前在本地下载S3文件,但我希望节省时间和带宽。 此外,如果RestClient确实将本地文件加载到内存中,那么在本地下载它并不能保存任何东西。 嘿嘿

任何建议将不胜感激。 谢谢 :)

更新:远程服务器只是一个响应发布请求的API。 我没有能力改变他们的结果。

看看: https : //github.com/rest-client/rest-client/blob/master/lib/restclient/payload.rb

RestClient肯定支持流式上传。 条件是在有效负载中传递不是字符串或散列的东西,并且传递的内容会响应读取和大小。 (所以基本上是一个流)。

在S3方面,你基本上需要抓取一个流,而不是在发送之前读取整个对象。 您使用http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html#get_object-instance_method并表示您希望在响应目标中获取IO对象(而不是字符串)。 为此,您可以使用IO.pipe

 reader, writer = IO.pipe fork do reader.close s3.get_object(bucket: 'bucket-name', key: 'object-key') do |chunk| writer.write(chunk) end end writer.close 

您将读者传递给RestClient :: Payload.generate并将其用作您的有效负载。 如果读取部分比写入部分慢,您可能仍会在内存中读取很多内容。 你想要的,写作时只接受你愿意在内存中缓冲的金额。 您可以使用writer.stat.size(在fork中)读取流的大小,并在超过一定大小时旋转它。