Rails 3 - use json to upload image
Asked Answered
L

1

8

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?

Lukin answered 17/12, 2012 at 10:3 Comment(1)
are sure about using JSON? - if so you have one field with all your user data in it ?Benefactor
B
17

- 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 ?

Benefactor answered 19/12, 2012 at 11:42 Comment(3)
from my Postman client is it possible to pass like this { "name":"xxx","image":"c:\Users\Images\ab.png" }Lukin
so then instead of { "image":"c:\Users\Images\ab.png" } paste the encoded version like { "image":"GIF89a\xB4\x00\x1F\x00\xE7\xFD...." } or adapt your code to handle posting an urlBenefactor
when i tried to upload through my view it works fine <%=f.input :image ,:as=>file %> , i have also given multipart=>true in my controller. i havent done anything in cintroller to convert it into base 64.From your above comment from where i get the encoded version,is it possible to give the path of the image because this image is uploading from iOS Application (front end),Ruby on rails Application act as backend in my project.How to solve this.Lukin

© 2022 - 2024 — McMap. All rights reserved.