我正在使用Rails + ActiveStorage上载图像文件,并希望在上载后在数据库中保存宽度和高度。但是,我在任何地方都找不到此类示例。
这是我从各种API文档中整理而来的,但最终出现此错误:private method 'open' called for #<String:0x00007f9480610118>
。将blob
替换为image.file
会导致Rails记录“由于ImageMagick不支持文件而跳过了图像分析”(https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/analyzer/image_analyzer.rb#L39)。
代码:
class Image < ApplicationRecord
after_commit { |image| set_dimensions image }
has_one_attached :file
def set_dimensions(image)
if (image.file.attached?)
blob = image.file.download
# error: private method `open' called for #<String:0x00007f9480610118>
meta = ActiveStorage::Analyzer::ImageAnalyzer.new(blob).metadata
end
end
end
此方法也有问题,因为在销毁时也会调用after_commit
。
TLDR:是否有“适当”的方式在上传后立即获取图像元数据?
我认为您可以在更新之前从javascript获取尺寸,然后将这些数据发布到控制器中。您可以查看一下:Check image width and height before upload with Javascript
回答自己的问题:我原来的解决方案已经结束,但是需要安装ImageMagick(不是,并且错误消息没有指出)。这是我的最终代码:
class Image < ApplicationRecord
attr_accessor :skip_set_dimensions
after_commit ({unless: :skip_set_dimensions}) { |image| set_dimensions image }
has_one_attached :file
def set_dimensions(image)
if (Image.exists?(image.id))
if (image.file.attached?)
meta = ActiveStorage::Analyzer::ImageAnalyzer.new(image.file).metadata
image.width = meta[:width]
image.height = meta[:height]
else
image.width = 0
image.height = 0
end
image.skip_set_dimensions = true
image.save!
end
end
end
我还使用this technique跳过了save!
上的回调,从而防止了无限循环。