2010-12-09 12 views
2

我正在编写一个Rails应用程序,它将存储在远程服务器上的文件提供给最终用户。替代Apache中用于发送给定URL的文件的X-sendfile?

在我的情况下,文件存储在S3上,但用户通过Rails应用程序请求文件(隐藏实际的URL)。如果该文件位于我的服务器本地文件系统上,那么我可以使用Apache头文件X-Sendfile为其他请求释放Ruby进程,同时Apache接管将文件发送到客户端的任务。但在我的情况下 - 文件不在本地文件系统中,而是在S3上 - 似乎我被迫在将其发送到客户端之前暂时将其下载到Rails中。

Apache没有办法将“远程”文件提供给实际上不在服务器上的客户端。我不介意Apache是​​否必须下载这个文件才能工作,只要我不必在Ruby进程中进行操作。

有什么建议吗?

+0

你需要在发送文件之前做一些Ruby的东西?你不能只重写URL,你需要隐藏S3的URL?只是为了澄清 – 2010-12-09 12:41:42

+0

不是真的,但我有两个要求:1)我想在日志中记录下载(如果客户端直接从S3请求文件,这是不可能的)。 2)我希望用户浏览器要求保存文件,而不是在浏览器窗口中显示它(今天我使用“Content-Disposition:attachment”标题)。我不知道是否可以强制将S3链接作为附件下载,而不是以内联方式显示。 – 2010-12-09 13:13:28

回答

0

托马斯,我有类似的要求/问题,我想我可以回答你的问题。首先(我不是100%确定你在乎这部分),隐藏S3网址很容易,因为Amazon允许你将CNAMES指向你的存储桶并使用自定义URL而不是亚马逊网址。为此,您需要将DNS指向正确的亚马逊网址。当我设置它时,它与此类似:files.domain.com指向files.domain.com.s3.amazonaws.com。然后,您需要使用自定义URL的名称(本例中为files.domain.com)创建存储桶。如何调用该URL将有所不同,具体取决于您使用的是哪种gem,但警告的一个字是我使用的attachment_fu插件错误地将我发送到files.domain.com/files.domain.com/name_of_file ....我找不到修复它的设置,所以插件S3部分的一个简单的.sub方法修复了它。

到您的其他问题,在下载你可以简单地做到这一点之前执行一些Rails代码(如记录在数据库命中):

def download 
    file = File.find(... 
    # code to record 'hit' to database 
    redirect_to 3Object.url_for(file.filename, 
           bucket, 
           :expires_in => 3.hours) 
end 

该代码将仍然导致被送达文件S3,但仍然可以让你运行一些ruby。 (当然,上面的代码不会按原样工作,您需要将它指向正确的文件和存储区,并且我的亚马逊键保存在配置文件中。上面还使用AWS :: S3 gem的语法 -​​)。

其次,Content-Disposition:附件问题有点棘手。希望你的情况比我的更简单,下面的解决方案可以工作。假设对象“文件”(在本例中)的正确的S3对象,则可以通过

file.content_disposition = "attachment" 
file.save 

上面的代码设定的处置附件可以执行S3服务器上存在的文件后(不像其他一些头和权限),这是很好的,它也可以在你上传文件时添加(语法取决于你的插件)。我仍然试图找到一种方式告诉S3将其作为附件发送,并且只有在被要求时(并非每次都发送),并且如果您发现这种情况,请让我知道您的解决方案。我需要有时可以下载它,并且其他时间可以将图像(例如)嵌入到HTML中。我没有使用上面提到的重定向,但幸运的是,如果您将内容处置/附件标头嵌入(例如HTML图像标记),并且浏览器仍然正常显示图像(但我没有通过足够的浏览器进行全面测试,以便在野外发送)。

希望有帮助!祝你好运。

相关问题