Carrierwave:通过替换原始版本(或:具有与原始文件不同的文件格式的版本)将上传的 PNG 转换为 JPG

Carrierwave: convert an uploaded PNG to JPG by replacing the original version (or: having versions with a different file format than original file)

我有以下型号:

class ScreenshotUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  storage :file
  convert :jpg

  version :thumb do
    process resize_to_fill: [50, 50]
  end

  def extension_whitelist
    %w(jpg jpeg gif png)
  end

  version :print do
    process border: ['black']
    process quality: 80
  end
end

通过 https://github.com/layerssss/paste.js and is saved as a base64 encoded string into a <textarea>, then uploaded using the https://github.com/y9v/carrierwave-base64 gem:

从剪贴板粘贴图像来上传图像
class Finding < ApplicationRecord
  mount_base64_uploader :screenshot, ScreenshotUploader
end

在HTML形式中,它看起来像这样:

上传后得到如下文件:

但我需要将原始文件也转换为JPG,因为我需要保存磁盘space。我怎样才能做到这一点?

你可以像carrier wave documentation上写的那样做 只需将 system("mogrify -resize '1200\>' #{file.file}") 替换为 system("mogrify -format jpg #{file.file}"),然后删除原始文件。

加上 Vasiliy 的回答,我得出以下结论:

  after :store, :convert_original_to_jpg

  def convert_original_to_jpg(new_file)
    if version_name.nil?
      system("mogrify -format jpg -quality 80  #{file.file}")
      system("unlink #{file.file}") # Remove the old PNG file
      model.update_column mounted_as, "#{mounted_as}.jpg" # The filename in the DB also needs to be manually set to .jpg!
    end
  end

虽然这适用于创建文件,但在更新文件时不起作用,因为 new_file 参数然后是 nil,因此所有图像都被删除。

我认为这是与 carrierwave-base64 gem 有关的一些怪癖,我没有任何进一步深入研究的动力。所以建议的解决方案可能不太有用,但为了文档,我想 post 在这里。

在我的特殊情况下,我决定放弃通过将 PNG 转换为 JPG 来节省磁盘空间的想法 space。相反,我只是设置 process quality: 80 以在版本上至少保存一些 space。

对于原始PNG(使用carrierwave-base64 gem无损保存),我简单地使用以下代码来缩小它的质量:

  after :store, :optimise_images

  def optimise_images(new_file)
    return if Rails.env.test? # Optimising consumes quite some time, so let's disable it for tests

    if version_name.nil?
      image_optim = ImageOptim.new pngout: false,
                                   svgo: false,
                                   pngcrush: false,
                                   optipng: false,
                                   pngquant: {allow_lossy: true}, # Everything disabled except pngquant, to keep the performance at a good level
                                   advpng: false
      image_optim.optimize_images!(Dir["#{File.dirname(file.file)}/*.png"])
    end
  end