Skip to content

Instantly share code, notes, and snippets.

@WizardOfOgz
Created June 7, 2011 12:13
Show Gist options
  • Select an option

  • Save WizardOfOgz/1012107 to your computer and use it in GitHub Desktop.

Select an option

Save WizardOfOgz/1012107 to your computer and use it in GitHub Desktop.
Save Base64-encoded images with Paperclip
class Avatar < ActiveRecord::Base
attr_accessor :content_type, :original_filename, :image_data
before_save :decode_base64_image
has_attached_file :image,
PAPERCLIP_CONFIG.merge(
:styles => {
:thumb => '32x32#',
:medium => '64x64#',
:large => '256x256#'
})
protected
def decode_base64_image
if image_data && content_type && original_filename
decoded_data = Base64.decode64(image_data)
data = StringIO.new(decoded_data)
data.class_eval do
attr_accessor :content_type, :original_filename
end
data.content_type = content_type
data.original_filename = File.basename(original_filename)
self.image = data
end
end
end
@AlanHassen

Copy link
Copy Markdown

How does your migration look like?

@matthuhiggins

Copy link
Copy Markdown

Paperclip automatically detects and supports base64 data, if the data uri format is used.

@mbusch

mbusch commented May 22, 2014

Copy link
Copy Markdown

@matthuhiggins could you explain that further, please? I would really appreciate your input on this!

@mbusch

mbusch commented Aug 29, 2014

Copy link
Copy Markdown

Sorry, I didn't recognized your answer until now - thanks, that really helps!

@KendrickIW

Copy link
Copy Markdown

@Exteris Can you explain how to use it?

@AndrewRayCode

Copy link
Copy Markdown

For anyone unlucky enough to try to do this, don't worry, I've gone through all the pain for you. This is all you need to add to your model class:

do_not_validate_attachment_file_type :image
has_attached_file :image, :default_url => "/whatever-who-cares.png"

And just make sure your POST data to update contains:

    {
    "model:" {
        "image:" "data:image/png;base64,iVBORw0KGgo..."
    }

You do not need any of the code in the original gist with PaperClip >= 4.0. The base64 io_adapter is auto-loaded by PaperClip, so it will act on any field matching the base64 regex, even though it's not documented at all.

@evan-007

evan-007 commented Nov 4, 2014

Copy link
Copy Markdown

@delvarworld thank you!

@mehulkar

mehulkar commented Jan 8, 2015

Copy link
Copy Markdown

@delvarworld do you set the filename manually? By default it seems to just get set to "data".

@AndrewRayCode

Copy link
Copy Markdown

Looking back at it, my images are all named data as well. I did not try sending a filename key, that might work.

@pjar

pjar commented Jan 20, 2015

Copy link
Copy Markdown

Having:

class Thing
    has_attached_file :image

and POST attributes:

 {
    "model:" {
        "image:" "data:image/png;base64,iVBORw0KGgo..."
     }
}

You need to specify original_filename for Thing. So for controller that would be:

image = Paperclip.io_adapters.for(params[:image]) 
image.original_filename = "something.png"
Thing.create(image: image)

original_filename was empty thus it was substituted here

@billychan

Copy link
Copy Markdown

@delvarworld, @pjar, I wish there is a upvote button next to your awesome comments.

@TangMonk

TangMonk commented Mar 9, 2015

Copy link
Copy Markdown

@delvarworld thanks!!

@augnustin

Copy link
Copy Markdown

Thanks.

@pjar, reading your comment, I understand that the filename is supposed to be accessed through another interface (sent in the form I guess).
But ain't there a way to deduce the extension (filename doesn't really matters) from the Base64 code itself? In data:image/png;base64,iVBO, image/png feels like a mimetype, right? Ain't there a pre-built paperclip method that would guess file extension?

@Tehyun

Tehyun commented Apr 21, 2015

Copy link
Copy Markdown

Thank you Ogz!

@avremel

avremel commented Apr 28, 2015

Copy link
Copy Markdown

Hi,

I am attempting to implement @pjar 's code into my controller but am getting stuck on Thing.create(image: image). I don't think I understand it, and therefore am failing to implement his solution in my code below:

  def create

    @form = Form.new(form_params)
    image = Paperclip.io_adapters.for(params[:base64])
    image.original_filename = "something.png"
    @form.image = image

    if @form.save
      flash[:success] = "The form has been successfully created!"
      redirect_to @form
    else
      render 'new'
    end
  end

@avremel

avremel commented Apr 29, 2015

Copy link
Copy Markdown

@dominiceden

dominiceden commented Sep 4, 2016

Copy link
Copy Markdown

Thanks @delvarworld and @pjar - really helpful. I have also found that you can just include the original filename in the params too and Paperclip will automatically include it in the image processing and use it for the newly generated image.

e.g.

{ "model": { "image": "data:image/png;base64,iVBORw0KGgo...", "image_file_name": "file.png" } }

This is particularly useful if you are POSTing the base64 encoded image to a Rails API via a web app - as you can get the filename of the image via the FileReader HTML5 API and submit it in your POST request, like above. Hope this helps someone.

@sarink

sarink commented Mar 8, 2018

Copy link
Copy Markdown

This is no longer included by default in v5. You have to register the DataUri IO adapter, see more here: https://github.com/thoughtbot/paperclip#io-adapters

You should still pass an image_file_name like above, though.

@MohamedHegab

Copy link
Copy Markdown

@sarink I've include Paperclip::DataUriAdapter.register in paperclip.rb and still don't upload the image

@bbugh

bbugh commented May 24, 2018

Copy link
Copy Markdown

This is so easy!

If you're on paperclip 5.1.0 you don't need to use the Paperclip::DataUriAdapter.register, it's still included by default. I believe they only changed this with 5.2.0

@Leoxxid

Leoxxid commented Nov 21, 2018

Copy link
Copy Markdown

Here it is saving only original format, any suggestion?
Paperclip 5.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment