Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 - use json to upload image

In my Rails 3 application I have multiple models, and each model is associated with another model.

User model

has_many :departments
accepts_nested_attributes_for :departments

Department Model

has_many :projects
accepts_nested_attributes_for :projects

I am trying to insert data through the postman REST client using JSON. I have found some of the formats except there is an image upload field in the User model that I am going to handle with the PaperClip gem.

Through my rails view it is working fine, but how do I upload an image using postman?

For uploading through REST client I need the JSON format equivalent of my image.

Is there any way to embed the image in json so I can use the postman rest client?

like image 407
Cyber Avatar asked Dec 17 '12 10:12

Cyber


1 Answers

- Using Base64

What is Base64
When you have some binary data that you want to ship across a network, you generally don't do it by just streaming the bits and bytes over the wire in a raw format. Why? because some media are made for streaming text. You never know -- some protocols may interpret your binary data as control characters (like a modem), or your binary data could be screwed up because the underlying protocol might think that you've entered a special character combination (like how FTP translates line endings).

So to get around this, people encode the binary data into characters. Base64 is one of these types of encodings. Why 64? Because you can generally rely on the same 64 characters being present in many character sets, and you can be reasonably confident that your data's going to end up on the other side of the wire uncorrupted.

-- Taken from What is base 64 encoding used for?


So one way of doing it is to put a Base64 string inside your json request and have your app decode it.

 # Your request
 {
    'user':{
     # .... 
         'picture':'GIF89a\xB4\x00\x1F\x00\xE7\xFD....'
     }
 }

Here is what your model could do

 class User < ActiveRecord::Base
   def convert_from_base64(image_data)
     data = StringIO.new(Base64.decode64(image_data))
     data.class.class_eval { attr_accessor :original_filename, :content_type }

     tmp = Tempfile.new("base64")
     tmp.write(data.read)
     tmp.close

     # only on *nix
     data.content_type = IO.popen(["file", "--brief", "--mime-type",tmp.path], 
        in: :close, err: :close).read.chomp
     data.original_filename = "picture." + data.content_type.split("/").last

     data
   end
 end


 # in your controller
 def create
   image_data = JSON.parse(params[:json])['user']['picture'] #or which ever field it is
   params[:user][:picture] = @user.convert_from_base64(image_data)
   # ....  
 end

But a quick look at POSTMAN tells me you have to do the encoding your self.


Alternatively
you can just pass a url instead of the data - if the url is pointing to resource available on the net.

require "open-uri"

class User < ActiveRecord::Base
  def picture_from_url(url)
    self.picture = open(url)
  end
end
# then just do 
user.picture_from_url params[:user][:photo_url]

Update
Postman actually allows you to construct a post request with an image attached. Isnt that what you are looking for ?

like image 61
krichard Avatar answered Oct 03 '22 10:10

krichard