Ruby on rails 如何复制Rails 5.2中ActiveStorage中存储的文件

Ruby on rails 如何复制Rails 5.2中ActiveStorage中存储的文件,ruby-on-rails,rails-activestorage,Ruby On Rails,Rails Activestorage,我有一个使用ActiveStorage的模型: class Package < ApplicationRecord has_one_attached :poster_image end 更新您的模型: class Package < ApplicationRecord has_one_attached :poster_image end 如果需要文件的完整副本,以便原始记录和克隆记录都有自己的附加文件副本,请执行以下操作: 在Rails 5.2中,抓取并将其放入confi

我有一个使用ActiveStorage的模型:

class Package < ApplicationRecord
  has_one_attached :poster_image
end
更新您的模型:

class Package < ApplicationRecord
  has_one_attached :poster_image
end

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

在Rails 5.2中,抓取并将其放入
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之后(无论何时发布),您都可以这样做:

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的贡献。:)

通过查看Rails的测试,特别是

那么这个案子呢

class Package < ApplicationRecord
  has_one_attached :poster_image
end
同样的方法适用于有许多附件的

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
class PostStringIO.new(image.download),
:filename=>image.filename,
:content\u type=>image.content\u type
结束
在rails 5中运行良好。对于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)
资料来源:

这对我很有效:

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

本杰明的回答稍有变化对我来说确实管用

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 
  })


我发现我还必须将dependent选项设置为false,以避免在删除原始包时删除blob:
has\u one\u attached:poster\u image,dependent:false
Yes!抱歉忘记了。除非我遗漏了什么,否则这不会创建文件的副本。它只是使两个记录指向同一个文件。而且,即使与文件相关的所有记录都被销毁,它也会将文件留在存储系统中。实际上,您确定这是最新的吗?我刚试过。似乎
ActiveStorage::PurgeJob
确实从“活动存储附件”中选择了1,其中“活动存储附件”。“blob\u id”=55 LIMIT 1
,如果有其他附件引用该blob,则不会删除该blob。所以
dependent:false不应该是必需的吗?我指的是。不幸的是,除了master.Works之外,第二部分仍然没有在Rails版本中发布。谢谢非常感谢。这个带有文件名和内容类型的扩展版本适用于我为什么这不是最重要的答案?:)
  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)
copy.poster_image.attach(original.poster_image.blob)
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 
  })