我正在制作带付费下载的网络应用程序,并且我遵循了Carrierwave的protecting uploads指南。一切都在拯救一件事。这是我目前的设置:
产品文件上传器
...
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}"
只需上传到名为downloads的public
目录中的新文件夹,这不是我想要做的。
有关如何进行的任何建议?感谢。
编辑:
我发现将Carrierwave配置文件中的config.root
设置为Rails.root
可以解决此问题。如果我执行此操作,请在我的ProductFileUploader
中将store_dir
指定为"downloads/#{model.product_id}/#{model.id}
。
但是,这意味着使用“/ public / ...”链接保存公共文件。 Rails会自动丢弃公共foldername并在URL中使用子目录名称。
答案 0 :(得分: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"
文件夹中。但是,这意味着rails会显示如下所示的URL
/public/downloads/myfile.jpg
这会带来一个问题,因为Rails会忽略路径中的public
。所以上面会404.但是当上传者继承我定义root
的特殊类时,我可以简单地说
def store_dir
"downloads/#{model.product_id}/#{model.id}"
end
它会正确上传和显示图像!希望这可以帮助别人。