2016-12-26 69 views
2

我正在製作一個帶有付費下載的webapp,我遵循Carrierwave的指南protecting uploads。一切工作都在期待着拯救一件事。這裏是我的當前設置:顯示Rails Carrierwave URL,無需公開整個路徑


產品文件上傳

... 
def store_dir 
    "#{Rails.root}/downloads/#{model.product_id}/#{model.id}" 
end 
... 

路線

get "/downloads/:product_id/:product_file_id/:filename", :controller => "products", action: "download", conditions: {method: :get} 

的ProductsController

def download 
    product_file = ProductFile.find(params[:product_file_id]) 
    name = File.basename(product_file.file.file.file) 
    send_file "#{Rails.root}/downloads/#{product_file.product.id}/#{product_file.id}/#{name}", :x_sendfile => true 
end 

問題出在下載路徑。由於我在文件上傳器中指定了#{Rails.root},因此該文件保存在名爲downloads的公用文件夾的外部文件夾中。然而,這具有意想不到的副作用。當我從模型中檢索URL時,我得到了完整的絕對路徑,而不是相對於Rails Root的路徑。

因此,例如,ProductFile.first.file.url返回"/home/doomy/Documents/resamplr/downloads/3/1/aaaa.zip",而應該只返回/downloads/3/1/aaa.zip

此行爲似乎附加在ProductFileUploader中指定的內容上。

例如,如果我將store_dir更改爲"/downloads/#{model.product_id}/#{model.id}",我在嘗試上傳到我的PC的根目錄時遇到訪問錯誤。 "downloads/#{model.product_id}/#{model.id}"只是簡單地上傳到public目錄中的一個新文件夾,稱爲下載,這不是我想要做的。

有關如何進行的任何建議?謝謝。


編輯:

我發現,在Carrierwave配置文件到Rails.root設置config.root允許這種行爲。如果我這樣做,在我的ProductFileUploader我可以指定store_dir"downloads/#{model.product_id}/#{model.id}

但是,這意味着公共文件將保存在「/ public/...」鏈接中。 Rails自動放棄公用文件夾名稱並使用URL中的子目錄名稱。

回答

1

發現瞭如何解決這個問題!

在每個上傳器中,有一種叫做root的特殊方法,我們可以用它來設置不可見的文件路徑。首先,我創建了一個稱爲PublicUploader的特殊上傳器基類。

class PublicUploader < CarrierWave::Uploader::Base 
    def root 
    "${Rails.root}/public" 
    end 
end 

然後,我將全局CarrierWave根設置爲Rails.root。

CarrierWave.configure do |config| 
    # These permissions will make dir and files available only to the user running 
    # the servers 
    config.permissions = 0600 
    config.directory_permissions = 0700 
    config.storage = :file 

    # This avoids uploaded files from saving to public/ and so 
    # they will not be available for public (non-authenticated) downloading 
    config.root = Rails.root 
end 

這意味着在我的私人文件上傳,我可以簡單地寫

def store_dir 
    "downloads/#{model.product_id}/#{model.id}" 
end 

,它會在"#{Rails.root}/downloads/..."保存,而不是"#{Rails.root}/public/downloads/..."。這意味着我可以使用控制器來限制訪問。

然而,在我的公開上傳,我根本就...

def store_dir 
    "public/downloads/#{model.product_id}/#{model.id}" 
end 

...因爲我想在我的"#{Rails.root}/public"文件夾中保存。然而,這意味着軌道將顯示類似下面的

/public/downloads/myfile.jpg

這就帶來了一個問題,一個URL,如Rails的省略從路徑public。所以上述404然而,當上傳從專班,我定義root繼承,那麼我可以簡單地說

def store_dir 
    "downloads/#{model.product_id}/#{model.id}" 
end 

它將上傳和正確顯示圖像!希望這可以幫助某人。