2010-12-09 39 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圖像標記),並且瀏覽器仍然正常顯示圖像(但我沒有通過足夠的瀏覽器進行全面測試,以便在野外發送)。

希望有幫助!祝你好運。