Carrierwave:文件名/ store_dir中的文件哈希和模型ID [英] Carrierwave: file hash and model id in filename/store_dir
问题描述
我在Rails 4项目中使用了载波,用于文件存储进行开发和测试,并在雾存储中(用于存储在Amazon S3上)进行生产。
I'm using carrierwave in a Rails 4 project with the file storage for development and testing and the fog storage (for storing on Amazon S3) for production.
我想使用以下路径保存文件:
I would like to save my files with paths like this:
/model_class_name/part_of_hash/another_part_of_hash/hash-model_id.file_extension
(例如: /images/12/34/1234567-89.png
其中1234567是SHA1文件内容的哈希值,而89是数据库中关联图像模型的ID)。
(example: /images/12/34/1234567-89.png
where 1234567 is the SHA1 hash of the file content and 89 is the id of the associated image model in the database).
到目前为止,我尝试过的操作是:
What I tried so far is this:
class MyUploader < CarrierWave::Uploader::Base
def store_dir
"#{model.class.name.underscore}/#{sha1_for(file)[0..1]}/#{sha1_for(file)[2..3]}"
end
def filename
"#{sha1_for(file)}-#{model.id}.#{file.extension}" if original_file
end
private
def sha1_for file
Digest::SHA1.hexdigest file.read
end
end
这不起作用,因为:
-
model.id
在调用文件名
时不可用 -
文件
在调用store_dir
时并不总是可用
model.id
is not available whenfilename
is calledfile
is not always available whenstore_dir
is called
所以,出现我的问题:
- 是否可以在
文件名
中使用模型ID /属性? 此链接说不应该这样做; - 是否可以在
store_dir
中使用文件内容/属性?我没有找到任何相关文档,但到目前为止我的经历是否(请参见上文)。 - 如何实现文件/目录命名,以使内容与我概述的内容尽可能接近
- is it possible to use model ids/attributes within
filename
? This link says it should not be done; is there a way to work around it? - is it possible to use file content/attributes within
store_dir
? I found no documentation on this but my experiences so far say "no" (see above). - how would you implement file/directory naming to get something as close as possible to what I outlined in the beginning?
推荐答案
-
包括ID由于文件名存储在数据库中,但ID尚不可用,因此在创建时不能使用文件名中的。 (公认的,极端的)解决方法是在create上使用一个临时值,然后在
after_commit :: create
上移动文件并更改数据库中的名称。可能可以通过after_create
对此进行优化,但我将由您自己决定。 (这是载波实际上传的位置文件)。Including the id in the filename on create may not be possible, since the filename is stored in the database but the id isn't available yet. An (admittedly rather extreme) workaround would be to use a temporary value on create, and then
after_commit on: :create
, move the file and change the name in the database. It may be possible to optimize this with anafter_create
, but I'll leave that up to you. (This is where carrierwave actually uploads the file.)在
store_dir
中直接包含文件属性 不可能,因为store_dir
用于计算url
-url
将需要知道sha1,这需要访问文件,这需要知道url,等等。解决方法非常明显:将感兴趣的属性(在本例中为sha1)缓存在模型的数据库记录,并在store_dir
中使用。Including file attributes directly within the
store_dir
isn't possible, sincestore_dir
is used to calculate theurl
—url
would require knowing the sha1, which requires having access to the file, which requires knowing the url, etc. The workaround is pretty obvious: cache the attributes in which you're interested (in this case the sha1) in the model's database record, and use that in thestore_dir
.id-in-文件名方法是使用其他值(例如uuid),并将该值存储在数据库中。关于此处。
The simpler variant on the id-in-filename approach is to use some other value, such as a uuid, and store that value in the database. There are some notes on that here.
这篇关于Carrierwave:文件名/ store_dir中的文件哈希和模型ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!