I want to upload a file from an Android client to a Rails JSON API server.
I'm sending a Multipart/form request from the Android client which looks like that:
Content-Type: multipart/form-data; boundary=d99ArGa2SaAsrXaGL_AdkNlmGn2wuflo5
Host: 10.0.2.2:3000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
--d99ArGa2SaAsrXaGL_AdkNlmGn2wuflo5
Content-Disposition: form-data; name="POSTDATA"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
{"tags":["test"],"location_id":1,"post":{"content":"test"}}
--d99ArGa2SaAsrXaGL_AdkNlmGn2wuflo5
Content-Disposition: form-data; name="IMAGEDATA"; filename="testimage.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
<BINARY DATA?
--d99ArGa2SaAsrXaGL_AdkNlmGn2wuflo5--
in the rails controller i'm creating the new post with this code:
@parsed_json = JSON(params[:POSTDATA])
@post = @current_user.posts.new(@parsed_json["post"])
how do I make Paperclip save the attachment from the multipart form ?
I can do it with something like this:
if params.has_key?(:IMAGEDATA)
photo = params[:IMAGEDATA]
photo.rewind
@filename = "/tmp/tempfile"
File.open(@filename, "wb") do |file|
file.write(photo.read)
end
@post.photo = File.open(@filename)
end
but it doesn't look like the best solution, also, the filename that is being passed in ther multipart request is not used.
The pure json way to do this is to not pass content-type multipart-form and pass the file as a base64 encoded string in the json.
I figured this out thanks this post: http://www.rqna.net/qna/xyxun-paperclip-throws-nohandlererror-with-base64-photo.html
Here's an example of the json:
"{\"account\":{\"first_name\":\"John\",\"last_name\":\"Smith\",\"email\":\"[email protected]\",\"password\":\"testtest\",\"avatar\":{\"data\":\"INSERT BASE64 ENCODED STRING OF FILE HERE\",\"filename\":\"avatar.jpg\",\"content_type\":\"image/jpg\"}}}"
Then in the controller process the incoming avatar like this before saving the model.
def process_avatar
if params[:account] && params[:account][:avatar]
data = StringIO.new(Base64.decode64(params[:account][:avatar][:data]))
data.class.class_eval { attr_accessor :original_filename, :content_type }
data.original_filename = params[:account][:avatar][:filename]
data.content_type = params[:account][:avatar][:content_type]
params[:account][:avatar] = data
end
end
So, I'm guessing your Post
model looks something like this:
class Post < ActiveRecord::Base
has_attached_file :photo, :styles => { ... }
...
end
So you should be able to do something as simple as this:
@post.photo = params[:IMAGEDATA] if params[:IMAGEDATA].present?
@post.save if @post.valid?
And it should save the photo.
If you need to do something more complicated, try re-arranging the form data into the data that the format Paperclip expects. And if you need to dig deeper, take a look inside Paperclip's Paperclip::Attachment
class.
Stack Overflow Cross-Reference
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With