我正在使用Rails + ActiveStorage上传图片文件,希望在上传后将宽度和高度保存在数据库中,但是我在任何地方都找不到这样的例子。
这是我从各种API文档中拼凑出来的,但最终出现了以下错误:将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
这种方法也存在问题,因为在destroy时也调用了after_commit
。
**TLDR:**是否有一种“正确”的方法可以在上传后立即获取图像元数据?
3条答案
按热度按时间u4vypkhs1#
解决方案内置导轨
根据ActiveStorage概述指南,已有一个使用ActiveStorage::Analyzer::ImageAnalyzer的现有解决方案
image.file.analyze
和image.file.analyze_later
(docs根据#analyze docs:
当新的blob第一次被附加时,它会通过analyze_later自动地进行异步分析。
这意味着您可以通过以下方式访问图像尺寸
因此,您的模型可能如下所示:
对于90%的常规情况,您可以很好地处理此问题
但是:问题是这是“异步分析”(
#analyze_later
),这意味着在上传后不会立即存储元数据这意味着,如果您需要真实的访问宽度/高度(例如,API对新上传文件尺寸的响应),则可能需要执行以下操作
注:在作业中异步执行此操作是有原因的。由于需要执行此额外代码,请求的响应速度会稍慢。因此,您需要有“立即保存维”的好理由
此解决方案的镜像可在How to store Image Width Height in Rails ActiveStorage中找到
DIY解决方案
建议:不要这样做,依赖现有的VanillaRails解决方案
需要更新附件的型号
Bogdan Balan's solution将工作。下面是相同解决方案的重写,但没有
skip_set_dimensions
attr_accessorupdate_columns docs
不需要更新附件的型号
很有可能你正在创建一个模型,你想在其中存储文件附件,并且不再更新它。(所以如果你需要更新附件,你只需要创建新的模型记录并删除旧的)
在这种情况下,代码就更加流畅了:
您可能希望在保存之前验证附件是否存在。
测试
文章attaching Active Storange to Factory Bot解释了
FilesTestHelper.jpg
的工作原理vuktfyat2#
回答自己的问题:我最初的解决方案很接近,但是需要安装ImageMagick(它没有安装,错误消息也没有指出这一点)。
我还使用this technique跳过
save!
上的回调,防止无限循环。fumotvh33#
我想你可以在更新之前从javascript中获取维度,然后将这些数据发布到controller中。你可以检查一下:Check image width and height before upload with Javascript