如何在Rails 5.2中复制存储在ActiveStorage中的文件

时间:2018-04-03 13:35:18

标签: ruby-on-rails rails-activestorage

我有一个使用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

6 个答案:

答案 0 :(得分:13)

更新您的型号:

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

答案 1 :(得分:9)

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

在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

谢谢乔治,您的原始答案和您对Rails的贡献。 :)

答案 2 :(得分:4)

在导轨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)

来源:

答案 3 :(得分:1)

通过查看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

copy.images.each do |image|
  copy.images.attach io: StringIO.new(original.poster_image.download),
                     filename: original.poster_image.filename,
                     content_type: original.poster_image.content_type
end

答案 4 :(得分: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 
  })

答案 5 :(得分:0)

对我有用:

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