12

I'm trying to upload an image file via http post method from android device to rails server. But posting an image is not working. More specifically, the post parameter (including image file) doesn't seem to be sent correctly.

I'm using Android Asynchronous Http Client (http://loopj.com/android-async-http/) to post an image from android, and the code for posting image is like this.

public static void postImage(){
    RequestParams params = new RequestParams();
    params.put("picture[name]","MyPictureName");
    params.put("picture[image]",File(Environment.getExternalStorageDirectory().getPath() + "/Pictures/CameraApp/test.jpg"));
    AsyncHttpClient client = new AsyncHttpClient();
    client.post("http://x.x.x.x:3000/pictures/", params, new AsyncHttpResponseHandler() {
        @Override
        public void onSuccess(String response) {
            Log.w("async", "success!!!!");
        }                                                                                                                                                                     
    }); 
}   

As for rails paperclip application, I simply used scaffold and generated model named "pictures" and added paperclip attached file on it. Model and controller (which receives the request) is like below.

model

class Picture < ActiveRecord::Base                                                                                                                                            
  attr_accessible :name, :image
  has_attached_file :image,
                    :styles => { :original => "480x480>", :thumbnail => "100x100>" },
                    :path => ':rails_root/public/system/pictures/image/:id_partition/:style_:filename'
end

controller

# POST /pictures                                                                                                                                                              
# POST /pictures.json
def create
  @picture = Picture.new(params[:picture])

  respond_to do |format|
    if @picture.save
      format.html { redirect_to @picture, notice: 'Picture was successfully created.' }
      format.json { render json: @picture, status: :created, location: @picture }
    else
      format.html { render action: "new" }
      format.json { render json: @picture.errors, status: :unprocessable_entity }
    end
  end
end

When receiving the request, "rails server" console says something like following

Started POST "/pictures/" for y.y.y.y at 2012-09-03 18:23:00 +0900
Processing by PicturesController#create as HTML
  Parameters: {"picture"=>{"name"=>"PictureName"}}
   (0.1ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "pictures" ("album_id", "created_at", "image_content_type", "image_file_name", "image_file_size", "image_updated_at", "name", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)  [["album_id", nil], ["created_at", Mon, 03 Sep 2012 09:23:00 UTC +00:00], ["image_content_type", nil], ["image_file_name", nil], ["image_file_size", nil], ["image_updated_at", nil], ["name", "PictureName"], ["updated_at", Mon, 03 Sep 2012 09:23:00 UTC +00:00], ["user_id", nil]]
[paperclip] Saving attachments.
   (11.0ms)  commit transaction
Redirected to http://x.x.x.x:3000/pictures/10                                                                                                                               
Completed 302 Found in 15ms (ActiveRecord: 11.6ms)

As you can see, there's only one paramater sent and "picture[image]" parameter which is raw image data is not received. Can anyone help me?

Ryo
  • 2,003
  • 4
  • 27
  • 42

3 Answers3

12

Sorry, that was my silly mistake. I should have done

params.put("picture[image]", new File(Environment.getExternalStorageDirectory().getPath() + "/Pictures/CameraApp/test.jpg"));

not

params.put("picture[image]", File(Environment.getExternalStorageDirectory().getPath() + "/Pictures/CameraApp/test.jpg"));

Should use New File not File

When using Android Asynchronous Http Client (http://loopj.com/android-async-http/), we don't have to care about MultipartEntity. Thank you to all guys who answered my question!!!!

AZ_
  • 21,688
  • 25
  • 143
  • 191
Ryo
  • 2,003
  • 4
  • 27
  • 42
  • I write a same code in my application, but many times server give me error because image size is large, Do you know any way to send a large image to server – Ashish Dwivedi Apr 02 '14 at 12:11
1

You can upload the Images via the MultipartEntity.

MultipartEntity, part of HttpMime 4.0 and later. Allows you to put multiple parts, separated by boundary strings and encoded using given charset, into httppost request.

For more info and how to use Multipart, see this and this.

Community
  • 1
  • 1
Shrikant Ballal
  • 7,067
  • 7
  • 41
  • 61
  • Please see one more link that I have added in my answer. – Shrikant Ballal Sep 03 '12 at 10:18
  • Thank you very much for your answer!!! Now, I understand using MultipartEntity, by instanciating MultipartEntity and applying addPart method on it, then invoke setEntity method to HttpPost instance. But What I'm using is not HttpPost class, but AsyncHttpClient class. Could you tell me how to do the same on AsyncHttpClient? – Ryo Sep 03 '12 at 10:31
  • Ahhh... sorry, Do you know how to do the same (use MultipartEntity) on AsyncHttpClient? – Ryo Sep 03 '12 at 10:34
0

There's a description like below, in Android AsyncHttpClient official page (http://loopj.com/android-async-http/)

"Multipart file uploads with no additional third party libraries"

and in the section of "Uploading Files with RequestParams", they have a sample code to upload an image

File myFile = new File("/path/to/file.png");
RequestParams params = new RequestParams();
try {
    params.put("profile_picture", myFile);
} catch(FileNotFoundException e) {}

This is what I did, though didn't work. Does this help answering my question?

Ryo
  • 2,003
  • 4
  • 27
  • 42