如何避免在 ActiveStorage 中接受损坏的图像?

问题描述 投票:0回答:2

我目前正在将一个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 方法来尝试创建一个variant。 ImageMagick 尝试转换调整损坏图像的大小但失败:

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.

因此,一旦上传了这样的损坏图像,应用程序每次尝试显示它都会失败。很容易拒绝服务。

我的理解:

  1. 文件被接受,然后“.save”方法成功。损坏的文件刚刚保存到磁盘。
  2. 稍后,ActiveStorage 启动后台作业来分析文件:
    [ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: 91055878-f516-4f2f-98ff-e39573980b45) to Async(active_storage_analysis) with arguments
  3. 作业运行并打印“跳过图像分析,因为 ImageMagick 不支持该文件”(来源:https://github.com/rails/rails/blob/fcb5f9035fd1307c300f4ab31fda353bd6365fc3/activestorage/lib/active_storage/analyzer/image_analyzer.rb #L39
  4. 作业写入元数据并将文件标记为“已识别”和“已分析”。 ActiveStorage::Blob Update (1.0ms) UPDATE "active_storage_blobs" SET "metadata" = $1 WHERE "active_storage_blobs"."id" = $2 [["metadata", "{\"identified\":true,\"analyzed\":true}"], ["id", 21670]]
    我真正想要的:

if new_screenshot.valid?

行对文件运行验证并发现它已损坏。
  1. 不会发生“.save”。错误消息已添加到闪现消息中。
    
    
  2. 经过几个小时的挫折后,我将非常感激任何提示。这是 ActiveStorage 或 active_storage_validations gem 中的错误吗?谢谢。
  3. [我很想念回形针。 ActiveStorage 似乎还没有提供相同的功能。]

上述效果是由于验证不完整造成的。

Active Storage 即使在验证失败后仍然检测附件
ruby-on-rails paperclip rails-activestorage
2个回答
0
投票
https://github.com/igorkasyanchuk/active_storage_validations/issues/91

对我来说最好的解决方案是不通过损坏图像的验证。 为此,我检查了尺寸参数的验证,因为损坏的图像永远不会有尺寸值。


0
投票

我还使用了这 3 个宝石来让一切正常工作

#Gemfile

gem "active_storage_validations" gem "ruby-vips" gem "image_processing"

© www.soinside.com 2019 - 2024. All rights reserved.