ruby-on-rails - ActiveStorage 是否可以创建用于直接上传的 blob 并在上传完成之前将其附加到模型?

标签 ruby-on-rails amazon-s3 rails-activerecord rails-activestorage

我正在创建一个包含文件上传服务的 api,其中上传的文件可以包含用户输入的额外信息,存储在项目模型中。当客户端请求从服务器直接上传时,我还想创建一个新项目并在客户端上传到 S3 时附加 blob。但是,如果 S3 中尚不存在 Blob,则 ActiveStorage 似乎不允许附加该 Blob。

我考虑了何时附加 Blob 的几个不同选项,但我认为在创建 Blob 和直接上传凭据时执行此操作是满足我需求的最佳选择。由于我需要一些 ActiveStorage 提供的默认 Controller 未涵盖的额外逻辑,因此我编写了自己的逻辑。在其中,我创建用于直接上传的 blob,创建项目,将 blob 附加到项目,并返回签名的上传 url、标题和项目 ID。但是,当我尝试将 blob 附加到项目时,它给了我一个 Aws::S3::Errors::NoSuchKey 错误。

在我的 Controller 中:

Project.transaction do
    # Create a project with default attributes
    project = create_draft_project(project_title)

    # Create a blob before direct upload to generate a signed url
    blob = ActiveStorage::Blob.create_before_direct_upload!(
        filename: filename,
        byte_size: byte_size,
        checksum: checksum,
        content_type: content_type
    )

    # Attach the blob to the project. This is where it errors.
    project.file.attach(blob.signed_id)
end

# Render the success response
success_response(project, blob)

在我的项目模型中:

has_one_attached :file

我希望 ActiveStorage 可以让我附加 blob,即使它尚未上传,但它实际上确实会在执行此操作之前检查该文件是否存在于 S3 中。这样做是有道理的,但似乎没有办法跳过检查。

最佳答案

我认为我在上传之前附加 blob 的原因实际上并没有我想象的那么深思熟虑。我不再试图绕过 S3 检查,但我在调查时确实找到了原始问题的解决方案。
ActiveStorage::BlobActiveStorage::Attachment 实际上都是 ActiveRecord::Base 的子类。这意味着您基本上可以将它们视为普通模型。 ActiveStorage::Attachment 被设置为多态关联,以在 ActiveStorage::Blob 和任何其他记录之间创建多对多关系。您需要做的就是使用正确的参数调用 ActiveStorage::Attachment.create 来设置新创建的 blob 和记录之间的关系。

问题中的代码将被重写为:

Project.transaction do
    # Create a project with default attributes
    project = create_draft_project(project_title)

    # Create a blob before direct upload to generate a signed url
    blob = ActiveStorage::Blob.create_before_direct_upload!(
        filename: filename,
        byte_size: byte_size,
        checksum: checksum,
        content_type: content_type
    )

    # Attach the blob to the project by creating the association in the database directly.
    ActiveStorage::Attachment.create(
        name: 'file',
        record_type: 'Project',
        record_id: project.id,
        blob_id: blob.id
    )
end

# Render the success response
success_response(project, blob)

关于ruby-on-rails - ActiveStorage 是否可以创建用于直接上传的 blob 并在上传完成之前将其附加到模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57057189/

相关文章:

ruby-on-rails - Rails 使用 has_and_belongs_to_many 进行预加载

ruby-on-rails - Rails/Unicorn 部署 : what creating the Unix socket?

ruby-on-rails - 如何在 Rails 应用程序中重新排序表列?

node.js - 覆盖低级 node.js 模块

ruby-on-rails - 如何对现有记录(历史数据)进行 rails 迁移?

ruby-on-rails - 如何计算 Ruby on Rails 中 bool 列的总和

ruby-on-rails - 在 Rails Controller 中处理所需参数的最佳方式?

amazon-web-services - 什么是 Amazon S3 中的 HeadBucket 操作

amazon-web-services - 如何允许使用 Amazon 托管的站点嵌入 iFrame 中?

ruby-on-rails - Rails 3 忽略 Postgres 唯一约束异常