2011-10-07 43 views
1

是否有可能在用戶右鍵單擊+保存之前重命名文件名,如同Carrierwave + S3 + Heroku + Content-Disposition一樣?在將文件保存在S3服務器上並將原始文件名保存在數據庫中的列中之前,我正在考慮清理文件名(例如193712391231.flv)。在Carrierwave + S3 + Heroku + Content-Disposition中用戶右鍵單擊+保存之前是否可以重命名文件名?

當用戶決定下載文件時(右鍵單擊並另存爲)。我無法提供/發送它爲193712391231.flv。相反,我想用原始文件名發送文件。

這是如何實現的?

使用Carrierwave。我遇到這樣的:

uploaded = Video.first.attachment 
uploader.retrieve_from_store!(File.basename(Video.first.attachment.url)) 
uploader.cache_stored_file! 

send_file uploader.file.path 

這不會通過S3提供服務​​,因爲它首先緩存在本地文件系統中的文件,然後將其發送到瀏覽器。它佔用了整個Web進程(Heroku中的Dyno)。

如果有人有任何想法,請提出建議。

回答

0

如果您直接從S3向用戶發送文件,您沒有選擇。如果您通過測功機發送文件,您可以將其稱爲您想要的內容,但是您在整個下載過程中都使用測功機。

我會盡可能以用戶友好的方式存儲文件,並使用文件夾來組織它們。

3

Akshully,您可以:

# minimal example, 
# here using mongoid, but it doesn't really matter 

class Media 

    field :filename, type: String # i.e. "cute-puppy" 
    field :extension, type: String # i.e. "mp4" 

    mount_uploader :media, MediaUploader 

end 

class MediaUploader < CarrierWave::Uploader::Base 

    # Files on S3 are only accessible via signed URLS: 
    @fog_public = false 

    # Signed URLS expire after ...: 
    @fog_authenticated_url_expiration = 2.hours # in seconds from now, (default is 10.minutes) 

    # MIME-Type and filename that the user will see: 
    def fog_attributes 
    { 
     "Content-Disposition" => "attachment; filename*=UTF-8''#{model.filename}", 
     "Content-Type" => MIME::Types.type_for(model.extension).first.content_type 
    } 
    end 

    # ... 
end 

URL中的model.media.url收益率將會再返回如下標頭:

Accept-Ranges:bytes 
Content-Disposition:attachment; filename*=UTF-8''yourfilename.mp4 
Content-Length:3926746 
Content-Type:video/mpeg 
Date:Thu, 28 Feb 2013 10:09:14 GMT 
Last-Modified:Thu, 28 Feb 2013 09:53:50 GMT 
Server:AmazonS3 
... 

然後,瀏覽器將強制下載(在瀏覽器中打開代替)和使用您設置的文件名,而不管文件名用於在存儲桶中存儲什麼東西。這樣做的唯一缺點是當Carrierwave創建文件時會設置Content-Disposition標題,因此您不能在同一文件中爲不同的用戶使用不同的文件名。

在這種情況下,你可以使用RightAWS生成標識的URL:

class Media 

    def to_url 
    s3_key = "" # the 'path' to the file in the S3 bucket 

    request_header = {} 
    response_header = { 
     "response-content-disposition" => "attachment; filename*=UTF-8''#{filename_with_extension}", 
     "response-content-type" => MIME::Types.type_for(extension).first.content_type 
    } 

    RightAws::S3Generator.new(
     Settings.aws.key, 
     Settings.aws.secret, 
     :port => 80, 
     :protocol => 'http'). 
     bucket(Settings.aws.bucket). 
     get(s3_key, 2.hours, request_header, response_header) 
    end 
end 

編輯:這是沒有必要使用RightAWS,uploader#url支持壓倒一切的響應頭,語法是隻是有點混亂(如一切與CarrierWave,恕我直言,但它仍然很棒):

Media.last.media.url(query: {"response-content-disposition" => "attachment; filename*=UTF-8''huhuhuhuhu"}) 

# results in: 
# => https://yourbucket.s3.amazonaws.com/media/512f292be75ab5a46f000001/yourfile.mp4?response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27huhuhuhuhu&AWSAccessKeyId=key&Signature=signature%3D&Expires=1362055338