我正在制作带有付费下载的Web应用程序,并且遵循了Carrierwave的保护上传。一切都按预期进行,可以节省一件事。这是我当前的设置:
I'm making a webapp with paid downloads, and I followed Carrierwave's guide for protecting uploads. Everything is working as expecting save one thing. Here's my current setup:
产品文件上传器
... 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根的路径。
The problem is with the download path. Because I specified #{Rails.root} in the File Uploader, the file saves in a folder external from the public folder called downloads. This has an unintended side effect, however. When I retrieve the URL from my model, I get the entire absolute path, not the path relative to the Rails Root.
例如, ProductFile.first.file.url 返回 / home / doomy / Documents / resamplr / downloads / 3/1 / aaaa.zip ,它应该只返回 /downloads/3/1/aaa.zip 。
So for instance, ProductFile.first.file.url returns "/home/doomy/Documents/resamplr/downloads/3/1/aaaa.zip", when it should instead just return /downloads/3/1/aaa.zip.
此行为似乎与 ProductFileUploader 中指定的行为有关。
This behaviour seems to be attached to what is specified in the ProductFileUploader.
例如,如果我将 store_dir 更改为 / downloads /#{model.product_id} / #{model.id} ,由于它试图上传到PC的根目录时出现访问错误。 downloads /#{model.product_id} /#{model.id} 只需上传到公开称为下载的目录,这不是我想要的。
For instance, if I change the store_dir to "/downloads/#{model.product_id}/#{model.id}", I get an access error as it is trying to upload to the root of my PC. "downloads/#{model.product_id}/#{model.id}" simply uploads to a new folder in the public directory called downloads, which is not what I want to do.
有关如何进行操作的任何建议?谢谢。
Any advice on how to proceed? Thanks.
编辑:
我发现该设置在Carrierwave配置文件中的 config.root 到 Rails.root 允许这种行为。如果这样做,则可以在 ProductFileUploader 中将 store_dir 指定为 downloads /# {model.product_id} /#{model.id} 。
I have found that setting the config.root in a Carrierwave config file to the Rails.root allows for this behavior. If I do this, in my ProductFileUploader I can specify the store_dir as "downloads/#{model.product_id}/#{model.id}.
但是,这意味着公共文件以 / public /保存。 ..链接。Rails自动丢弃公用文件夹名称,并在URL中使用子目录名称。
However, this means public files are saved with a "/public/..." link. Rails automatically discards the public foldername and uses subdirectory names in the URL.
推荐答案找出了解决方法!
在每个上传器中,都有一个名为 root 的特殊方法,我们可以使用它来设置看不见的文件路径。首先,我制作了一个特殊的上载器基类,称为PublicUploader。
In each uploader, there is a special method called root that we can use to set the unseen filepath. First, I made a special uploader base class called PublicUploader.
class PublicUploader < CarrierWave::Uploader::Base def root "${Rails.root}/public" end end然后,我将全局CarrierWave根目录设置为Rails.root。
Then, I set the global CarrierWave root to the 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
这意味着在我的私人文件上传器中,我可以简单地编写
This means in my private file uploader I can simply write
def store_dir "downloads/#{model.product_id}/#{model.id}" end,它将保存为#{Rails.root} / downloads /...\"反对#{Rails.root} / public / downloads /...\"。这意味着我可以使用控制器来限制访问。
and it will save in "#{Rails.root}/downloads/..." as opposed to "#{Rails.root}/public/downloads/...". This means I can use a controller to limit access.
但是,在我的公共上传器中,我只是......
However, in my public uploader, I simply had...
def store_dir "public/downloads/#{model.product_id}/#{model.id}" end...因为我想保存在我的#{Rails.root} / public 文件夹中。但是,这意味着Rails将显示如下所示的网址
...because I wanted to save in my "#{Rails.root}/public" folder. However, this meant that rails would show a url like the following
/public/downloads/myfile.jpg
这带来了一个问题,因为Rails忽略了路径中的 public 。因此,上面的代码将是404。但是,当上传者从我定义 root 的特殊类继承时,我可以简单地说
This poses a problem, as Rails omits the public from the path. So the above would 404. However when the uploader inherits from the special class where I define the root, then I can simply say
def store_dir "downloads/#{model.product_id}/#{model.id}" end它将上传并正确显示图像!希望这可以帮助某人。
It will upload and show the image correctly! Hope this can help someone.
更多推荐
在不暴露整个路径的情况下显示Rails Carrierwave URL
发布评论