显示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
它会正确上传和显示图像! 希望这可以帮助别人。