Rails ActiveStorage 附加到现有 S3 文件

Posted

技术标签:

【中文标题】Rails ActiveStorage 附加到现有 S3 文件【英文标题】:Rails ActiveStorage attachment to existing S3 file 【发布时间】:2019-02-18 19:04:51 【问题描述】:

我正在构建一个 PDF 解析器,它会触发 Sidekiq 工作人员以 OCR 解析存储在 S3 中的文档中的数据。解析后,数据存储在 Document 模型中。

如何在不复制 S3 中的文件(通过 File.open 等...)的情况下将现有 S3 存储桶文件附加到 ActiveStorage 中的Document.attachment.attach

【问题讨论】:

我快速阅读了 activestorage 的源代码,不幸的是我认为这还不可能。我也想要这个功能。 此外,github.com/rails/rails/issues/30819 的方向不正确 【参考方案1】:

这可以通过在创建后对 blob 进行轻微操作来完成。

storage.yml

amazon:
  service: S3
  access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
  secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
  region: <%= ENV['AWS_REGION'] %>
  bucket: <%= ENV['S3_BUCKET'] %>

app/models/document.rb

class Document < ApplicationRecord
  has_one_attached :pdf
end

rails 控制台

key = "<S3 Key of the existing file in the same bucket that storage.yml uses>"

# Create an active storage blob that will represent the file on S3
params =  
  filename: "myfile.jpg", 
  content_type:"image/jpeg", 
  byte_size:1234, 
  checksum:"<Base 64 encoding of the MD5 hash of the file's contents>" 

blob = ActiveStorage::Blob.create_before_direct_upload!(params)

# By default, the blob's key (S3 key, in this case) a secure (random) token
# However, since the file is already on S3, we need to change the 
# key to match our file on S3
blob.update_attributes key:key

# Now we can create a document object connected to your S3 file
d = Document.create! pdf:blob.signed_id

# in your view, you can now use
url_for d.pdf

此时,您可以像使用任何其他活动存储附件一样使用Document 对象的pdf 属性。

【讨论】:

【参考方案2】:

Troy 的回答对我很有帮助!我还发现从对象的 s3 实例中提取有关对象的元数据很有帮助。比如:

s3 = Aws::S3::Resource.new(region: "us-west-1")
obj = s3.bucket("my-bucket").object("myfile.jpg")    

params = 
    filename: obj.key, 
    content_type: obj.content_type, 
    byte_size: obj.size, 
    checksum: obj.etag.gsub('"',"")

我只有 46 分,所以我将此作为答案而不是评论:/

【讨论】:

根据您的需要,您可能希望使用File.basename(obj.key) 作为文件名。

以上是关于Rails ActiveStorage 附加到现有 S3 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 Rails 5.2 ActiveStorage 创建和保存 pdf 并稍后附加到电子邮件

如何在 ActiveStorage (Rails 5.2) 中更新附件

使用不同的文件名附加 ActiveStorage blob

Rails activestorage 不适用于 shopify_app gem

如何从 Rails Active Storage 中的 url 附加图像

如何将文档附加到电子邮件 ActiveStorage 和 Cloudinary?