如何将现有云存储对象关联到Rails Active Storage附件属性
已存在Cloud Storage对象关联Rails Active Storage附件的实现说明
仅回传Cloud Storage侧的对象键无法直接完成附件关联,文档示例中的
signed_blob_id和云存储侧的对象标识是完全独立的两个概念。
signed_blob_id是Rails侧ActiveStorage::Blob数据库记录的签名标识符,由Rails使用项目密钥生成,存储着附件的元数据、存储位置等核心信息。如果云函数直接将文件上传到存储桶、Rails侧没有提前创建对应Blob记录,既不存在合法的signed_blob_id,直接传入对象键调用attach方法也会因找不到对应Blob记录抛出错误。
你可以根据自己的业务流程选择对应实现方案:
- 适配现有云函数直传存储桶的流程
云函数完成文件上传后,不要只返回存储对象键,需要同时回传以下文件元数据给Rails:存储桶内的对象完整key、文件字节大小、文件MIME类型、文件原始文件名。Rails侧收到参数后,手动创建指向已存在存储对象的Blob记录,再完成附件关联,参考代码如下:
注意:必须保证云函数上传文件使用的存储桶、访问权限和Rails Active Storage配置的Cloud Storage信息完全一致,否则关联后会出现文件无法访问的问题。# 接收云函数传回的参数 storage_object_key = params[:storage_object_key] file_byte_size = params[:file_byte_size] file_content_type = params[:file_content_type] file_original_name = params[:file_original_name] # 创建绑定已有云存储对象的Blob记录 blob = ActiveStorage::Blob.create_after_upload!( key: storage_object_key, filename: file_original_name, content_type: file_content_type, byte_size: file_byte_size, service_name: :google # 替换为config/storage.yml中配置的Cloud Storage对应服务名 ) # 完成模型与附件的关联 person.avatar.attach(blob) - 符合Active Storage原生设计的优化流程
如果可以调整现有链路,建议改用预创建Blob的模式,长期维护成本更低,也不需要手动对齐元数据:- 云函数生成待上传文件后,先请求Rails侧的预上传接口,由Rails创建未绑定业务模型的Blob记录,返回对应的
signed_blob_id和Cloud Storage预签名上传地址 - 云函数持有预签名地址直接将文件上传到Cloud Storage指定位置
- 上传完成后云函数请求业务接口,直接将
signed_blob_id传回Rails,此时即可直接使用文档示例的写法完成关联:
person.avatar.attach(params[:signed_blob_id]) - 云函数生成待上传文件后,先请求Rails侧的预上传接口,由Rails创建未绑定业务模型的Blob记录,返回对应的
重要提醒:不要尝试在云函数侧伪造signed_blob_id,该值由Rails使用项目secret_key_base签名生成,外部服务无法计算出合法值,伪造ID会直接触发签名校验错误。
内容的提问来源于stack exchange,提问作者Patrick Vellia
相关产品推荐
相关产品推荐

