如何避免在 ActiveStorage 中接受损坏的图像?
How can I avoid accepting broken images in ActiveStorage?
我目前正在将 Rails 应用程序(驱动 screenshots.debian.net)从 Paperclip 迁移到 ActiveStorage。它允许用户上传 PNG 图像,然后向所有用户显示。
TL;DR: 上传表单接受损坏的图片。 Imagemagick“接受”它们。 ActiveStorage 不会立即验证这一点。我最终在磁盘上看到损坏的文件。
这是图片的模型。我正在使用 'active_storage_validations' gem:
class Screenshot < ApplicationRecord
has_one_attached :image
validates :image, attached: true, content_type: [:png]
def medium_image
if self.image.attached?
self.image.variant(
resize_to_limit: [670, 600]
).processed
end
end
end
从具有文件字段的 HTML 表单接收上传的控制器逻辑:
def upload_receive
@package = Package.find_by!(name: params[:name])
params[:file].each do |img|
new_screenshot = @package.screenshots.new(image: img)
if new_screenshot.valid?
new_screenshot.save
end
end
end
这很好用。接受 PNG 文件。 JPG 文件被拒绝。不错
然而,当我上传一个故意损坏的文件时,我 运行 遇到了麻烦。我创建了一个名为“broken.png”的文件,其中包含 5 KB 的零字节。 ActiveStorage 接受该文件,所以我得到了一个无效文件。
上传后图像应该立即显示。调用 Screenshot.medium_image 方法尝试创建 变体 。 ImageMagick 尝试 convert 调整损坏图像的大小但失败:
convert /tmp/ActiveStorage-21670-… failed with error:
convert-im6.q16: improper image header `/tmp/ActiveStorage-21670-…' @ error/png.c/ReadPNGImage/4092.
convert-im6.q16: no images defined `/tmp/image_processing….png' @ error/convert.c/ConvertImageCommand/3258.
因此,一旦上传了这样一张损坏的图片,应用程序每次尝试显示它时都会失败。相当简单的拒绝服务。
我的理解:
- 文件被接受,然后“.save”方法成功。损坏的文件刚刚保存到磁盘。
- 不久之后 ActiveStorage 启动后台作业来分析文件:
[ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: 91055878-f516-4f2f-98ff-e39573980b45) to Async(active_storage_analysis) with arguments
- 作业 运行s 并打印“跳过图像分析,因为 ImageMagick 不支持该文件”(来源:https://github.com/rails/rails/blob/fcb5f9035fd1307c300f4ab31fda353bd6365fc3/activestorage/lib/active_storage/analyzer/image_analyzer.rb#L39)
- 作业写入元数据并将文件标记为 已识别 和 已分析。
ActiveStorage::Blob Update (1.0ms) UPDATE "active_storage_blobs" SET "metadata" = WHERE "active_storage_blobs"."id" = [["metadata", "{\"identified\":true,\"analyzed\":true}"], ["id", 21670]]
我真正想要的是:
if new_screenshot.valid?
行 运行s 验证文件并发现它已损坏。
- 不会发生“.save”。一条错误消息被添加到 flash 消息中。
经过几个小时的挫折,如果有任何提示,我将不胜感激。这是 ActiveStorage 或 active_storage_validations gem 中的错误吗?谢谢。
[我很想念回形针。 ActiveStorage 似乎还没有提供相同的功能。]
上述效果是由于验证不完整造成的。 and the upstream issue is kept in https://github.com/igorkasyanchuk/active_storage_validations/issues/91
中提供了解决方法
我目前正在将 Rails 应用程序(驱动 screenshots.debian.net)从 Paperclip 迁移到 ActiveStorage。它允许用户上传 PNG 图像,然后向所有用户显示。
TL;DR: 上传表单接受损坏的图片。 Imagemagick“接受”它们。 ActiveStorage 不会立即验证这一点。我最终在磁盘上看到损坏的文件。
这是图片的模型。我正在使用 'active_storage_validations' gem:
class Screenshot < ApplicationRecord
has_one_attached :image
validates :image, attached: true, content_type: [:png]
def medium_image
if self.image.attached?
self.image.variant(
resize_to_limit: [670, 600]
).processed
end
end
end
从具有文件字段的 HTML 表单接收上传的控制器逻辑:
def upload_receive
@package = Package.find_by!(name: params[:name])
params[:file].each do |img|
new_screenshot = @package.screenshots.new(image: img)
if new_screenshot.valid?
new_screenshot.save
end
end
end
这很好用。接受 PNG 文件。 JPG 文件被拒绝。不错
然而,当我上传一个故意损坏的文件时,我 运行 遇到了麻烦。我创建了一个名为“broken.png”的文件,其中包含 5 KB 的零字节。 ActiveStorage 接受该文件,所以我得到了一个无效文件。
上传后图像应该立即显示。调用 Screenshot.medium_image 方法尝试创建 变体 。 ImageMagick 尝试 convert 调整损坏图像的大小但失败:
convert /tmp/ActiveStorage-21670-… failed with error:
convert-im6.q16: improper image header `/tmp/ActiveStorage-21670-…' @ error/png.c/ReadPNGImage/4092.
convert-im6.q16: no images defined `/tmp/image_processing….png' @ error/convert.c/ConvertImageCommand/3258.
因此,一旦上传了这样一张损坏的图片,应用程序每次尝试显示它时都会失败。相当简单的拒绝服务。
我的理解:
- 文件被接受,然后“.save”方法成功。损坏的文件刚刚保存到磁盘。
- 不久之后 ActiveStorage 启动后台作业来分析文件:
[ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: 91055878-f516-4f2f-98ff-e39573980b45) to Async(active_storage_analysis) with arguments
- 作业 运行s 并打印“跳过图像分析,因为 ImageMagick 不支持该文件”(来源:https://github.com/rails/rails/blob/fcb5f9035fd1307c300f4ab31fda353bd6365fc3/activestorage/lib/active_storage/analyzer/image_analyzer.rb#L39)
- 作业写入元数据并将文件标记为 已识别 和 已分析。
ActiveStorage::Blob Update (1.0ms) UPDATE "active_storage_blobs" SET "metadata" = WHERE "active_storage_blobs"."id" = [["metadata", "{\"identified\":true,\"analyzed\":true}"], ["id", 21670]]
我真正想要的是:
if new_screenshot.valid?
行 运行s 验证文件并发现它已损坏。- 不会发生“.save”。一条错误消息被添加到 flash 消息中。
经过几个小时的挫折,如果有任何提示,我将不胜感激。这是 ActiveStorage 或 active_storage_validations gem 中的错误吗?谢谢。
[我很想念回形针。 ActiveStorage 似乎还没有提供相同的功能。]
上述效果是由于验证不完整造成的。