将上传的文件从 Active Storage 迁移到 Carrierwave
Migrating uploaded files from Active Storage to Carrierwave
出于各种原因,我正在将我的上传从 ActiveStorage (AS) 迁移到 CarrierWave (CW)。
我正在制作 rake 任务并整理逻辑 - 我对如何将 AS blob 馈送到 CW 文件感到困惑。
我正在尝试这样的事情:
@files.each.with_index(1) do | a, index |
if a.attachment.attached?
a.attachment.download do |file|
a.file = file
end
a.save!
end
end
这是基于这两个链接:
https://edgeguides.rubyonrails.org/active_storage_overview.html#downloading-files
message.video.open do |file|
system '/path/to/virus/scanner', file.path
# ...
end
和
https://github.com/carrierwaveuploader/carrierwave#activerecord
# like this
File.open('somewhere') do |f|
u.avatar = f
end
我在本地测试了这个,文件没有通过上传器加载。我的问题是:
- 我是不是漏掉了什么明显的东西?
- 我的方法有误吗,需要新的方法吗?
红利问题:
- 执行此操作时,我似乎看不到设置 CW 文件名的明确路径?
您从 attachment.download
块中获得的 file
对象是一个字符串。更准确地说,来自 .download
的响应是文件 "streamed and yielded in chunks"(参见 documentation)。我通过调用 file.class
验证了这一点,以确保 class 符合我的预期。
因此,要解决您的问题,您需要提供一个可以调用 .read
的对象。通常这是使用 Ruby StringIO class.
但是,考虑到 Carrierwave also expects a filename,您可以使用继承 StringIO
的辅助模型来解决它(来自上面链接的博文):
class FileIO < StringIO
def initialize(stream, filename)
super(stream)
@original_filename = filename
end
attr_reader :original_filename
end
然后你可以用a.file = FileIO.new(file, 'new_filename')
替换a.file = file
这是我最后的机架任务(基于已接受的答案)- 可以进行调整。对我有用吗:
namespace :carrierwave do
desc "Import the old AS files into CW"
task import: :environment do
@files = Attachment.all
puts "#{@files.count} files to be processed"
puts "+" * 50
@files.each.with_index(1) do | a, index |
if a.attachment.attached?
puts "Attachment #{index}: Key: #{a.attachment.blob.key} ID: #{a.id} Filename: #{a.attachment.blob.filename}"
class FileIO < StringIO
def initialize(stream, filename)
super(stream)
@original_filename = filename
end
attr_reader :original_filename
end
a.attachment.download do |file|
a.file = FileIO.new(file, a.attachment.blob.filename.to_s)
end
a.save!
puts "-" * 50
end
end
end
desc "Purge the old AS files"
task purge: :environment do
@files = Attachment.all
puts "#{@files.count} files to be processed"
puts "+" * 50
@files.each.with_index(1) do | a, index |
if a.attachment.attached?
puts "Attachment #{index}: Key: #{a.attachment.blob.key} ID: #{a.id} Filename: #{a.attachment.blob.filename}"
a.attachment.purge
puts "-" * 50
@count = index
end
end
puts "#{@count} files purged"
end
end
现在,在我的例子中,我正在逐步执行此操作 - 我已通过此 rake 任务和相关的 MCV 更新对我的 master 进行了分支。如果我的网站在真正的生产中,可能 运行 首先导入 rake 任务,然后确认一切顺利,然后清除旧的 AS 文件。
出于各种原因,我正在将我的上传从 ActiveStorage (AS) 迁移到 CarrierWave (CW)。
我正在制作 rake 任务并整理逻辑 - 我对如何将 AS blob 馈送到 CW 文件感到困惑。
我正在尝试这样的事情:
@files.each.with_index(1) do | a, index |
if a.attachment.attached?
a.attachment.download do |file|
a.file = file
end
a.save!
end
end
这是基于这两个链接:
https://edgeguides.rubyonrails.org/active_storage_overview.html#downloading-files
message.video.open do |file|
system '/path/to/virus/scanner', file.path
# ...
end
和
https://github.com/carrierwaveuploader/carrierwave#activerecord
# like this
File.open('somewhere') do |f|
u.avatar = f
end
我在本地测试了这个,文件没有通过上传器加载。我的问题是:
- 我是不是漏掉了什么明显的东西?
- 我的方法有误吗,需要新的方法吗?
红利问题:
- 执行此操作时,我似乎看不到设置 CW 文件名的明确路径?
您从 attachment.download
块中获得的 file
对象是一个字符串。更准确地说,来自 .download
的响应是文件 "streamed and yielded in chunks"(参见 documentation)。我通过调用 file.class
验证了这一点,以确保 class 符合我的预期。
因此,要解决您的问题,您需要提供一个可以调用 .read
的对象。通常这是使用 Ruby StringIO class.
但是,考虑到 Carrierwave also expects a filename,您可以使用继承 StringIO
的辅助模型来解决它(来自上面链接的博文):
class FileIO < StringIO
def initialize(stream, filename)
super(stream)
@original_filename = filename
end
attr_reader :original_filename
end
然后你可以用a.file = FileIO.new(file, 'new_filename')
a.file = file
这是我最后的机架任务(基于已接受的答案)- 可以进行调整。对我有用吗:
namespace :carrierwave do
desc "Import the old AS files into CW"
task import: :environment do
@files = Attachment.all
puts "#{@files.count} files to be processed"
puts "+" * 50
@files.each.with_index(1) do | a, index |
if a.attachment.attached?
puts "Attachment #{index}: Key: #{a.attachment.blob.key} ID: #{a.id} Filename: #{a.attachment.blob.filename}"
class FileIO < StringIO
def initialize(stream, filename)
super(stream)
@original_filename = filename
end
attr_reader :original_filename
end
a.attachment.download do |file|
a.file = FileIO.new(file, a.attachment.blob.filename.to_s)
end
a.save!
puts "-" * 50
end
end
end
desc "Purge the old AS files"
task purge: :environment do
@files = Attachment.all
puts "#{@files.count} files to be processed"
puts "+" * 50
@files.each.with_index(1) do | a, index |
if a.attachment.attached?
puts "Attachment #{index}: Key: #{a.attachment.blob.key} ID: #{a.id} Filename: #{a.attachment.blob.filename}"
a.attachment.purge
puts "-" * 50
@count = index
end
end
puts "#{@count} files purged"
end
end
现在,在我的例子中,我正在逐步执行此操作 - 我已通过此 rake 任务和相关的 MCV 更新对我的 master 进行了分支。如果我的网站在真正的生产中,可能 运行 首先导入 rake 任务,然后确认一切顺利,然后清除旧的 AS 文件。