Attachment_fu rotate image in S3 storage Rails

517 views Asked by At

How to rotate image in S3 storage, I'm using Attachment_fu and Amazon S3 , I want to implement a feature that lets users edit existing images by rotating it 90 degrees. I was wondering if anyone had played with this, or had any ideas. I'm currently using rmagick to rotate the image in Rails directory. But in AWS S3 storage cannot rotate the image.

require 'RMagick'

def rotate
    photo   = Photo.find(params[:id])
    image   = Magick::ImageList.new(photo.file)
    image   = image.rotate(90)
    image.write(photo.file)
end

I'm using this gem:

gem 'pothoven-attachment_fu'
gem 'aws-s3'
gem 'rmagick'
1

There are 1 answers

0
Marcelo Austria On

I solved this problem.

def update_photo
      require 'RMagick'
      require 'base64'

      # get the image data in Photo table
      @photo = Photo.where(id: params[:photo_id]).first

      # get image path in S3 url and encode to Base64 binary
      img_url = @photo.s3_url()
      img_uri = URI.parse(img_url)
      base64_image = Base64.encode64(open(img_uri) { |io| io.read })
      image_file_name = File.basename(img_uri.path,File.extname(img_uri.path))
      filename_path = "#{Rails.root.to_s}/tmp/#{image_file_name}"

      # create tempfile in rails root/tmp folder and decode the Base64 binary into image file, then processing RMagick to rotate the image into desire image rotation.
      @tempfile = Tempfile.new(filename_path)
      @tempfile.binmode
      @tempfile.write Base64.decode64(base64_image)
      @tempfile.close

      # rotate image using RMagick
      Magick::Image.read(img_uri).first.rotate!(params[:photo_degree].to_i).write(@tempfile.path)

      # for security we want the actual content type, not just what was passed in
      # get mime type of image and passed into ActionDispatch type
      content_type = `file --mime -b #{@tempfile.path}`.split(";")[0]

      # we will also add the extension ourselves based on the above
      # if it's not gif/jpeg/png, it will fail the validation in the upload model
      extension = content_type.match(/gif|jpeg|png/).to_s
      extension = "jpg" if extension == "jpeg"

      # append filename to prevent browser image caching
      filename_path += "_#{params[:photo_degree]}"

      filename_path += ".#{extension}" if extension

      # passed the data into  Rails core ActionDispatch instead of file input object
      file = ActionDispatch::Http::UploadedFile.new({
        tempfile: @tempfile,
        type: content_type,
        filename: filename_path
      })

      # delete the existing image
      @photo.destroy 

      # create new image
      img_rotate                = Photo.new()
      img_rotate.id             = @photo.id
      img_rotate.uploaded_data  = file
      img_rotate.save

       ensure
          clean_tempfile

end

  def clean_tempfile
    if @tempfile
      @tempfile.close
      @tempfile.unlink
    end
  end