如何在blobs表中为rails ActiveStorage计算校验和

时间:2018-06-02 13:53:30

标签: ruby-on-rails rails-activestorage

有人知道在rails 5.2 +上使用ActiveStorage时如何计算active_storage_blobs中的校验和字段?

对于奖励积分,是否有人知道我如何使用md5校验和来匹配md5 CLI命令中的校验和?

4 个答案:

答案 0 :(得分:2)

这是blob数据的base64编码的MD5摘要。我担心Active Storage不支持像md5(1)发出的十六进制校验和。遗憾!

答案 1 :(得分:2)

源代码在这里: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>

答案 2 :(得分:1)

让它分解

我知道我参加聚会有点晚了,但这对于那些在寻找答案的过程中遇到的人来说更是如此。所以就在这里。

背景:

Rails在5.2版中引入了许多新功能,其中之一是 ActiveStorage 。官方最终版本于2018年4月9日发布。

免责声明:

因此,非常清楚地说,以下信息与现成的 vanilla 主动存储有关。这也没有考虑到一些疯狂的代码功能,这些代码功能围绕某个关闭场景进行。

话虽如此,根据您的Active Storage设置,校验和的计算方式有所不同。使用香草的现成可用的Rails Active Storage,有2种“类型”(由于缺乏更好的术语)。

  1. 代理上传
  2. 直接上传

代理上传

文件上传流程: [客户端]→[RoR应用]→[存储服务]

Comm。流程: 可以有所不同,但在大多数情况下,应类似于文件上传流程。

SparkBao的答案中上面指出的是“代理上传”。这意味着您将文件上传到RoR应用程序并执行某种处理,然后再将文件发送到配置的存储服务(AWS,Azure,Google,BackBlaze等...)。即使您将存储服务设置为“ localdisk”,即使RoR应用程序是存储端点,该逻辑在技术上仍然适用。

代理上传”方法不适用于在Heroku等服务上的云中部署的RoR应用程序。 Heroku有30秒的硬性限制,可以完成交易并将响应发送回客户(最终用户)。因此,如果文件很大,则需要考虑文件上传所需的时间,然后考虑计算校验和的时间。如果您遇到无法在30秒内完成请求的响应的情况,则需要使用“ 直接上传”方法。

代理上传答案:

Spark.Bao指出的方法Digest::MD5中使用了Ruby类compute_checksum_in_chunks(io)


直接上传

文件上传流程: [客户端]→[存储服务]

Comm。流程: [客户端]→[RoR App]→[客户端]→[存储服务]→[客户端]→[RoR App]→[客户端]

我们维护和开发Rails的好朋友已经为我们完成了所有繁重的工作。我不会详细介绍如何设置直接上传,但是这里是有关»Rails EdgeGuide - Direct Uploads的链接。

代理上传答案:

现在说了这么多,借助开箱即用的“ 直接上传”设置,可以利用SparkMD5(JavaScript)计算文件校验和。

下面是Rails Active Storage Source Code- (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

答案 3 :(得分:0)

关于奖金问题(可能也是主要问题):

您可以将校验和从base64转换为十六进制(例如md5(1)命令支持)并返回。

Converting a hexadecimal digest to base64 in Ruby

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