显示Rails Carrierwave URL而不暴露整个路径

我正在制作带有付费下载的网络应用程序,我按照Carrierwave的指南来保护上传 。 一切都在拯救一件事。 这是我目前的设置:


产品文件上传器

... 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 

问题出在下载路径上。 因为我在File Uploader中指定了#{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}"只是上传到名为downloads的public目录中的新文件夹,这不是我想要做的。

关于如何进行的任何建议? 谢谢。


编辑:

我发现将Carrierwave配置文件中的config.root设置为Rails.root可以实现此行为。 如果我这样做,在我的ProductFileUploader我可以将store_dir指定为"downloads/#{model.product_id}/#{model.id}

但是,这意味着公共文件使用“/ public / …”链接保存。 Rails自动丢弃公共foldername并在URL中使用子目录名称。

找到了解决这个问题的方法!

在每个上传器中,有一个名为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"文件夹中。 但是,这意味着rails会显示如下所示的URL

/public/downloads/myfile.jpg

这带来了一个问题,因为Rails从路径中省略了public 。 所以上面会404.但是当上传者inheritance自我定义root的特殊类时,我可以简单地说

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

它会正确上传和显示图像! 希望这可以帮助别人。