Rails 4 CarrierWave (master) and MiniMagick: change file format
Asked Answered
B

0

7

I'm using Rails 4.2, CarrierWave master branch, and MiniMagick 4.3.6 (also using the CarrierWave::MiniMagick module).

According to the CarrierWave Docs it is possible to change the format of a file during the upload/processing stage.

However, I do not think the code works as documented. I'm using Amazon S3 as my store with the fog-aws gem, and the files that get uploaded to S3 retain their original format.

My end goal is to upload a PDF document and have it processed into a png file when I save it in S3.

When I upload image files, everything works as expected and they get into S3 properly as an image. PDF files, however, are stilled stored in S3 with a content-type of "application/pdf" and the browser tries to render them as PDFs instead of as images (if useful, my uploads are being used in an image slider).

Anyone know why the conversion process doesn't work properly?

Model (models/testimonial.rb):

class Testimonial < ActiveRecord::Base
  mount_uploader :image, TestimonialUploader
end

Uploader (uploaders/testimonial_uploader.rb):

class TestimonialUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  storage :fog

  process :convert_file_to_png => [850, 1100]

  def convert_file_to_png(width, height)
    manipulate! do |img|
      img.format("png") do |c|
        c.trim
        c.resize "#{width}x#{height}>"
        c.resize "#{width}x#{height}<"
      end

      img
    end
  end

  def extension_white_list
    %w(jpg jpeg png pdf bmp tif tiff)
  end

  def store_dir
    "testimonials/#{model.uuid}"
  end

  def filename
    super.chomp(File.extname(super)) + ".png" if original_filename.present?
  end
end

Update 2016-10-07: working code

I was asked to update this post with my solution. Below is working code I've been using in production for several months now without any known isues.

class TestimonialUploader < CarrierWave::Uploader::Base
  # 2015-12-23: note that ImageMagick does not actually seem to work
  include CarrierWave::RMagick

  # Scopes
  #----------------------------------------------------------------------

  # NOOP

  # Macros
  #----------------------------------------------------------------------

  storage :fog

  process convert_file_to_png: [850, 1100]
  process :set_content_type_to_png

  # Associations
  #----------------------------------------------------------------------

  # NOOP

  # Validations
  #----------------------------------------------------------------------

  # NOOP

  # Methods
  #----------------------------------------------------------------------

  def convert_file_to_png(width, height)
    manipulate!(format: "png", read: { density: 400 }) do |img, index, options|
      options = { quality: 100 }
      img.resize_to_fit!(width, height)
    end
  end

  # Required to actually force Amazon S3 to treat it like an image
  def set_content_type_to_png
    self.file.instance_variable_set(:@content_type, "image/png")
  end

  def extension_white_list
    %w(jpg jpeg png pdf bmp tif tiff)
  end

  def store_dir
    "testimonials/#{model.uuid}"
  end

  def filename
    super.chomp(File.extname(super)) + ".png" if original_filename.present?
  end
end
Belligerency answered 22/12, 2015 at 20:14 Comment(3)
You should add your solution or experience hereQuirt
Regarding "img.format("png")" in the manipulate! block - what if you don't want to convert to png? Say you want to allow jpg and png?Countrified
@Countrified you allow file types using the extension_white_list methodTrapeze

© 2022 - 2024 — McMap. All rights reserved.