Use paperclip for saving base64 images obtained from an api
Asked Answered
U

5

12

I have a Photo model with an image attribute. The image contains a base64 string obtained from an api. I need to run an after_create callback and I was thinking I could use Paperclip for saving the image to the disk in the callback as it would save me some work implementing the folder structure in the public folder and generating thumbnails. Is there an easy way to do that?

Unrepair answered 15/5, 2014 at 10:34 Comment(0)
U
19

To answer my own question, here is what I've come up with:

class Photo < ActiveRecord::Base

  before_validation :set_image

  has_attached_file :image, styles: { thumb: "x100>" }
  validates_attachment :image, presence: true, content_type: { content_type: ["image/jpeg", "image/jpg"] }, size: { in: 0..10.megabytes }

  def set_image
    StringIO.open(Base64.decode64(image_json)) do |data|
      data.class.class_eval { attr_accessor :original_filename, :content_type }
      data.original_filename = "file.jpg"
      data.content_type = "image/jpeg"
      self.image = data
    end
  end

end

image_json is a text field containing the actual base64 encoded image (just the data part, eg "/9j/4AAQSkZJRg...")

Unrepair answered 15/5, 2014 at 14:48 Comment(5)
hi,from the view did u pass the encoded string as a hidden field to the controller?and from the controller what did u do?Supervise
nothing special, just something like Photo.create!(image_json: i) where i is data from the params hash containing the base64 stringGenitive
how to write it from controller..it gives me image_json method undefinedUrea
@Urea add attr_accessor :image_json to your model.Teheran
Assigning 'data.content_type' is not reflexed at 'self.image=data'. Paperclip finds out the content type of the base64 passed immater of 'data.content_type'. So, problem with validating the content_type. How to solve this?!Revelationist
N
6

your set_image should look something like this

    def set_image        
       self.update({image_attr: "data:image/jpeg;base64," + image_json[PATH_TO_BASE64_DATA]})
    end
Northeaster answered 25/7, 2014 at 0:23 Comment(0)
A
3

At least with Paperclip 5 it works out of the box you need to provide base64 string with format data:image/jpeg;base64,#{base64_encoded_file}

For you model it will be

Photo.new(
   image:  "data:image/jpeg;base64,#{image_json}",
   image_file_name: 'file.jpg' # this way you can provide file_name
 )

Additionally in your controller you do not need to change anything:-) (maybe you would like to accept :image_file_name in params)

Affix answered 9/1, 2017 at 11:19 Comment(1)
Content-types with dots inside were fixed around 4.2, earlier versions also support base64-adapter, but only for easy content types (fix is regex replacement)Panthia
P
3

As of Paperclip 5.2 you need to register the DataUriAdapter for Paperclip to handle base64 images for you.

In config/initializers/paperclip put: Paperclip::DataUriAdapter.register

Then as @eldi says you can just do:

Photo.new(
   image:  "data:image/jpeg;base64,#{image_json}",
   image_file_name: 'file.jpg' # this way you can provide file_name
 )

(See Paperclip release notes here)

Piecrust answered 10/3, 2018 at 8:35 Comment(6)
I tried this but it says: ActiveModel::UnknownAttributeError (unknown attribute 'image' for Image.):Flat
Processing by ImagesController#create as */* Parameters: {"authenticity_token"=>"XXX", "data"=>"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAQABADASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAf/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAABgj/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABykX//Z"}Flat
I did add the Paperclip::DataUriAdapter.register -- any ideas what's going on? Paperclip 5.2. Thanks!Flat
@image = Image.new(uid: current_user.uid, image: params[:data], image_file_name: 'dataurl') Flat
Sorry for the delay @jywarren. It looks like you aren't using the correct attribute name for the attachment. In your Image model, where you are mounting paperclip, what is the name of the attached file. In the below example it's avatar. In my example it was image: has_attached_file :avatar Whatever it is, that's the attribute you need to use for submitting the image data.Piecrust
oh awesome, good catch! the attribute is photo not image in my project. Changing and pushing a new commit - hope it works: github.com/publiclab/plots2/pull/3619Flat
J
1
require 'RMagick'
data = params[:image_text]# code like this  data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABPUAAAI9CAYAAABSTE0XAAAgAElEQVR4Xuy9SXPjytKm6ZwnUbNyHs7Jc7/VV9bW1WXWi9q
image_data = Base64.decode64(data['data:image/png;base64,'.length .. -1])
new_file=File.new("somefilename.png", 'wb')
new_file.write(image_data)

After you kan use image as file Photo.new(image: image)#save useng paperclip in Photo model

Judgeship answered 11/12, 2014 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.