require 'digest' require 'json' class MaterialFileSha256 def self.blob_metadata blob metadata = blob.metadata return metadata if metadata.is_a?(Hash) return { } if metadata.blank? JSON.parse(metadata) rescue JSON::ParserError { } end def self.metadata_sha256 blob blob_metadata(blob)['sha256'].presence end def self.assign_metadata_sha256! blob, sha256 return if sha256.blank? metadata = blob_metadata(blob) metadata['sha256'] = sha256 blob.metadata = metadata blob.save! if blob.changed? end def self.from_blob blob, allow_download: false sha256 = metadata_sha256(blob) return sha256 if sha256.present? return nil unless allow_download begin blob.open do |file| sha256 = Digest::SHA256.file(file.path).hexdigest assign_metadata_sha256!(blob, sha256) sha256 end rescue ActiveStorage::FileNotFoundError, ArgumentError => error Rails.logger.warn( "MaterialFileSha256.from_blob failed for blob_id=#{blob.id}: " \ "#{error.class}: #{error.message}", ) nil end end def self.from_upload upload tempfile = upload&.tempfile return nil unless tempfile tempfile.rewind Digest::SHA256.file(tempfile.path).hexdigest.tap do tempfile.rewind end end end