【问题标题】:How do I duplicate a file stored in ActiveStorage in Rails 5.2如何在 Rails 5.2 中复制存储在 ActiveStorage 中的文件
【发布时间】:2018-09-12 20:46:51
【问题描述】:

我有一个使用 ActiveStorage 的模型:

class Package < ApplicationRecord
  has_one_attached :poster_image
end

如何创建包含初始 poster_image 文件副本的 Package 对象的副本。大致如下:

original = Package.first
copy = original.dup
copy.poster_image.attach = original.poster_image.copy_of_file

【问题讨论】:

    标签: ruby-on-rails rails-activestorage


    【解决方案1】:

    对本杰明的回答略有不同确实对我有用。

    copy.poster_image.attach({
        io: StringIO.new(original.poster_image.blob.download), 
        filename: original.poster_image.blob.filename, 
        content_type: original.poster_image.blob.content_type 
      })
    
    

    【讨论】:

    • 谢谢!这个带有文件名和 content_type 的扩展版本对我有用
    【解决方案2】:

    它对我有用:

    copy.poster_image.attach(original.poster_image.blob)
    

    【讨论】:

    • 为什么这不是最佳答案? :)
    【解决方案3】:

    通过查看 Rails 的测试找到答案,特别是 in the blob model test

    所以对于这种情况

    class Package < ApplicationRecord
      has_one_attached :poster_image
    end
    

    您可以这样复制附件

    original = Package.first
    copy = original.dup
    copy.poster_image.attach \
      :io           => StringIO.new(original.poster_image.download),
      :filename     => original.poster_image.filename,
      :content_type => original.poster_image.content_type
    

    同样的方法适用于has_many_attachments

    class Post < ApplicationRecord
      has_many_attached :images
    end
    
    original = Post.first
    copy = original.dup
    
    original.images.each do |image|
      copy.images.attach \
        :io           => StringIO.new(image.download),
        :filename     => image.filename,
        :content_type => image.content_type
    end
    

    【讨论】:

      【解决方案4】:

      在 rails 5 Jethro's answer 运行良好。对于 Rails 6,我必须修改为:

        image_io = source_record.image.download
        ct = source_record.image.content_type
        fn = source_record.image.filename.to_s
        ts = Time.now.to_i.to_s
      
        new_blob = ActiveStorage::Blob.create_and_upload!(
          io: StringIO.new(image_io),
          filename: ts + '_' + fn,
          content_type: ct,
        )
      
        new_record.image.attach(new_blob)
      

      来源:

      【讨论】:

      • 按预期工作。谢谢!
      【解决方案5】:

      更新您的模型:

      class Package < ApplicationRecord
        has_one_attached :poster_image
      end
      

      将源包的海报图像 blob 附加到目标包:

      source_package.dup.tap do |destination_package|
        destination_package.poster_image.attach(source_package.poster_image.blob)
      end
      

      【讨论】:

      • 我发现我还必须将依赖选项设置为 false 以避免在删除原始包时删除 blob:has_one_attached :poster_image, dependent: false
      • 是的!抱歉忘记了。
      • 除非我遗漏了什么,否则这不会创建文件的副本。它只是使两个记录都指向同一个文件。即使与文件关联的所有记录都被销毁,它也会将文件留在存储系统上。
      • 其实,你确定这是最新的吗?我刚试过。似乎ActiveStorage::PurgeJob 执行SELECT 1 AS one FROM "active_storage_attachments" WHERE "active_storage_attachments"."blob_id" = 55 LIMIT 1 并且如果有其他附件引用它,则不会删除该blob。所以dependent: false 不是必须的吗?
      • 我指的是this before destroy
      【解决方案6】:

      如果您想要文件的完整副本,以便原始记录克隆记录都有自己的附件副本,请执行以下操作:

      在 Rails 5.2 中,抓取 this code 并将其放入 config/initializers/active_storage.rb,然后使用此代码进行复制:

      ActiveStorage::Downloader.new(original.poster_image).download_blob_to_tempfile do |tempfile|
        copy.poster_image.attach({
          io: tempfile, 
          filename: original.poster_image.blob.filename, 
          content_type: original.poster_image.blob.content_type 
        })
      end
      

      在 Rails 5.2 之后(只要发布包含this commit),您就可以这样做:

      original.poster_image.blob.open do |tempfile|
        copy.poster_image.attach({
          io: tempfile, 
          filename: original.poster_image.blob.filename, 
          content_type: original.poster_image.blob.content_type 
        })
      end
      

      感谢 George,您的原始回答和 Rails 贡献。 :)

      【讨论】:

      • 很遗憾,除了master之外,第二部分仍然没有在Rails版本中发布。
      猜你喜欢
      • 2018-02-02
      • 2018-10-20
      • 2019-05-19
      • 1970-01-01
      • 2018-09-28
      • 2019-06-12
      • 2018-09-23
      • 1970-01-01
      • 2018-11-18
      相关资源
      最近更新 更多