有谁知道在 rails 5.2+ 上使用 ActiveStorage 时如何计算 active_storage_blobs 中的校验和字段?
对于奖励积分,有谁知道我怎样才能使用与 md5 CLI 命令中的校验和匹配的 md5 校验和?
有谁知道在 rails 5.2+ 上使用 ActiveStorage 时如何计算 active_storage_blobs 中的校验和字段?
对于奖励积分,有谁知道我怎样才能使用与 md5 CLI 命令中的校验和匹配的 md5 校验和?
我知道我参加聚会有点晚了,但这对于那些在寻找答案时遇到这个问题的人来说更是如此。所以在这里..
背景:
Rails 在 5.2 版本中引入了大量新特性,其中之一就是ActiveStorage。官方最终版本于 2018 年 4 月 9 日发布。
免责声明:
因此,为了清楚起见,以下信息与开箱即用的香草主动存储有关。这也没有考虑到一些围绕某个场景的疯狂代码fu。
话虽如此,校验和的计算方式会根据您的 Active Storage 设置而有所不同。使用 vanilla 开箱即用的 Rails Active Storage,有 2 种“类型”(因为没有更好的术语)配置。
文件上传流程: [Client] → [RoR App] → [Storage Service]
通讯。流程:可能会有所不同,但在大多数情况下,它应该类似于文件上传流程。
SparkBao 的回答上面指出的是“代理上传”。这意味着您将文件上传到您的 RoR 应用程序并在将文件发送到您配置的存储服务(AWS、Azure、Google、BackBlaze 等)之前执行某种处理。即使您将存储服务设置为“localdisk”,该逻辑在技术上仍然适用,即使您的 RoR 应用程序是存储端点。
“代理上传”方法对于在 Heroku 等服务上部署在云中的 RoR 应用程序并不理想。Heroku 有 30 秒的硬性限制来完成您的交易并将响应发送回您的客户(最终用户)。因此,如果您的文件相当大,您需要考虑文件上传所需的时间,然后考虑计算校验和所需的时间。如果您遇到无法在 30 秒内完成请求并做出响应的情况,您将需要使用“直接上传”方法。
代理上传答案:
正如 Spark.Bao所指出的,Ruby 类Digest::MD5用于方法compute_checksum_in_chunks(io) 。
文件上传流程:【客户端】→【存储服务】
通讯。流程: [Client] → [RoR App] → [Client] → [Storage Service] → [Client] → [RoR App] → [Client]
我们维护和开发 Rails 的好朋友已经为我们完成了所有繁重的工作。我不会详细介绍如何设置直接上传,但这里有一个关于如何设置的链接 » Rails EdgeGuide - Direct Uploads。
代理上传答案:
综上所述,使用开箱即用的“直接上传”设置,文件校验和是通过利用SparkMD5 (JavaScript) 计算的。
下面是来自Rails Active Storage 源代码的片段 - (activestorage.js)
var fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
var FileChecksum = function() {
createClass(FileChecksum, null, [ {
key: "create",
value: function create(file, callback) {
var instance = new FileChecksum(file);
instance.create(callback);
}
} ]);
function FileChecksum(file) {
classCallCheck(this, FileChecksum);
this.file = file;
this.chunkSize = 2097152;
this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
this.chunkIndex = 0;
}
createClass(FileChecksum, [ {
key: "create",
value: function create(callback) {
var _this = this;
this.callback = callback;
this.md5Buffer = new sparkMd5.ArrayBuffer();
this.fileReader = new FileReader();
this.fileReader.addEventListener("load", function(event) {
return _this.fileReaderDidLoad(event);
});
this.fileReader.addEventListener("error", function(event) {
return _this.fileReaderDidError(event);
});
this.readNextChunk();
}
},
如果有什么我错过了,我会提前道歉。我试图尽可能彻底。
因此,总结以下内容应该足以作为可接受的答案:
代理上传配置: ruby 类Digest::MD5
直接上传配置: JavaScript 哈希库SparkMD5。
源代码在这里:https ://github.com/rails/rails/blob/master/activestorage/app/models/active_storage/blob.rb#L234
def compute_checksum_in_chunks(io)
Digest::MD5.new.tap do |checksum|
while chunk = io.read(5.megabytes)
checksum << chunk
end
io.rewind
end.base64digest
end
在我的项目中,我需要使用这个校验和值来判断用户是否上传了重复文件,我使用以下代码与上述方法得到相同的值:
md5 = Digest::MD5.file(params[:file].tempfile.path).base64digest
puts "========= md5: #{md5}"
输出:
========= md5: F/9Inmc4zdQqpeSS2ZZGug==
数据库数据:
pry(main)> ActiveStorage::Blob.find_by(checksum: 'F/9Inmc4zdQqpeSS2ZZGug==')
ActiveStorage::Blob Load (2.7ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."checksum" = $1 LIMIT $2 [["checksum", "F/9Inmc4zdQqpeSS2ZZGug=="], ["LIMIT", 1]]
=> #<ActiveStorage::Blob:0x00007f9a16729a90
id: 1,
key: "gpN2NSgfimVP8VwzHwQXs1cB",
filename: "15 Celebrate.mp3",
content_type: "audio/mpeg",
metadata: {"identified"=>true, "analyzed"=>true},
byte_size: 9204528,
checksum: "F/9Inmc4zdQqpeSS2ZZGug==",
created_at: Thu, 29 Nov 2018 01:38:15 UTC +00:00>
它是 blob 数据的 base64 编码的 MD5 摘要。恐怕 Active Storage 不支持md5(1)发出的十六进制校验和。对不起!
对于您的奖金问题(可能也是主要问题):
您可以将校验和从 base64 转换为十六进制(如md5(1)命令支持)并返回。
def hex_to_base64(hexdigest)
Base64.strict_encode64([hex_string].pack("H*"))
end
从 base64 到十六进制:
def base64_to_hex(base64_string)
Base64.decode64(base64_string).each_byte.map { |b| "%02x" % b.to_i }.join
end