Subheader

Lazy Programmer's Blog

Pages

Friday, July 22, 2016

Rails Paperclip and SVG files

Paperclip has unpleasant handling of SGV files, so it corrupts SVG XML file, and finally uploaded original file will have just header.

Temporary dirty solution is to replace original SVG file. Lets assume we need to store jpg/png/gif/svg image, which can have thumbnail.

Model
class Image < ActiveRecord::Base
  has_attached_file :file,  styles: { thumb: {processors: [:image_thumb]}}
  validates_attachment_content_type :file,
    content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif", "image/svg+xml"]

  attr_accessor :tmp_stage_file_name
    attr_accessor :tmp_stage_file_ext
    before_post_process :save_staged_file
    after_save :replace_original_file

  def save_staged_file
        if (path = file.staged_path)
            if (file.content_type == 'image/svg+xml')               
                @tmp_stage_file_name = File.join("/tmp", SecureRandom.uuid)
                @tmp_stage_file_ext = File.extname(path)
                FileUtils.cp(path, File.join("/tmp", "#{tmp_stage_file_name}#{tmp_stage_file_ext}"))
            end
        end
    end

    def replace_original_file
        if !file.blank? && !tmp_stage_file_name.blank?
            path = File.join("/tmp", "#{tmp_stage_file_name}#{tmp_stage_file_ext}")
            if File.exist? path
                FileUtils.cp path, file.path
                FileUtils.rm path, force: true
            end
        end
        @tmp_stage_file_name = nil
        @tmp_stage_file_ext = nil
    end
end
Image Processor
lib/paperclip_processors/image_thumb.rb

module Paperclip
    class ImageThumb < Processor
        HEIGHT = 320
        WIDTH = 320
        def initialize file, options = {}, attachment = nil
      super
      @file = file
      @instance = options[:instance]
      @current_format   = File.extname(@file.path)
      @whiny = options[:whiny].nil? ? true : options[:whiny]
      @basename = File.basename(file.path, File.extname(file.path))
            @geometry = options[:geometry]
    end

    def make
      geometry = Paperclip::Geometry.from_file(@file)
      filename = [@basename, @current_format || ''].join
      dst = TempfileFactory.new.generate(filename)

            begin
                cmd = file.content_type != 'image/svg+xml' ?
                    %Q(convert '#{file.path}' -resize '#{WIDTH}x#{HEIGHT}^' -gravity 'center' -crop '#{WIDTH}x#{HEIGHT}+0+0' +repage '#{dst.path}') :
                    %Q(rsvg-convert -a -w #{WIDTH} -h #{HEIGHT} -f svg '#{file.path}' -o '#{dst.path}')
                Paperclip.run(cmd)
            rescue
                raise Paperclip::Error, "There was an error processing the thumbnail for #{@basename}" if @whiny
            end
      dst
    end
    end
end

No comments:

Post a Comment