我正在创建一个包含文件上传服务的 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::Blob
和 ActiveStorage::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/