开发者

Upload a photo with some parameters to a Ruby-on-rails web app using Objective-C and an ASIFormDataRequest for iOS

I need to upload a list of photos (can be one at a time) to my client's server from an iOS app (iOS 4). His server is using the Phusion Passenger 2.2.14 module on Apache Server (Ubuntu) to deploy his Ruby app.

Here is the Ruby code my client used to upload a photo using a Ruby rest client and it worked for one image. He mentonned that the image should be in an array but since here we are only sending one image, it worked.

resource = RestClient::Resource.new 'http://serveraddress.com/id.json', :user => '********', :password => '*****'

resource.put :property => {:new_images => {:public => '0',:t_viewable => '0', :l_viewable => '0', :name => 'name3', :room => 'Bathroom', :attachment_type => 'periodic', :attached_file => File.new('/Users/me/Pictures/12618298.jpg','rb')} }

My question is, how should I encode this data using Objective-C collections? Authentication works fine.

Here is the code I am using, but it gets a 500 Internal Server Error:

[request setPostValue:photoName forKey:@"property[new_images][0][name]"];

[request setPostValue:[NSString stringWithFormat:@"%f",[[NSDate date] timeIntervalSince1970]] forKey:@"property[new_images][0][created_at]"];

[request setFile:photoPathFull withFileName:[self.localCaptions objectAtIndex:index] andContentType:@"image/jpeg"
          forKey:@"property[new_images][0][attached_file]"];

[request setPostValue:self.room forKey:@"property[new_images][0][room]"];

[request setPostValue:imageCategory forKey:@"property[new_images][0][attachment_type]"];

[request setPostValue:public forKey:@"property[new_images][0][public]"];
[request setPostValue:tViewable forKey:@"property[new_images][0][t_viewable]"];
[request setPostValue:lViewable forKey:@"property[new_images]开发者_如何学运维[0][l_viewable]"];

*Note that the request variable is an ASIFormDataRequest object.

He also specified the server expects the following parameters:

property[new_images][1][name]=Sink
property[new_images][1][created_at]=<timestamp>
property[new_images][1][attached_file]=<filedata>
property[new_images][1][room]=Kitchen 
property[new_images][1][attachment_type]=periodic
property[new_images][1][public]=0
property[new_images][1][t_viewable]=0
property[new_images][1][l_viewable]=0

Thanks,


I finally got access to the errors log on the server side, so here is what it looks like:


ActiveRecord::UnknownAttributeError: unknown attribute: 0

{"format"=>"json",
 "property"=>
  {"new_images"=>
    {"0"=>
      {"tenant_viewable"=>"0",
       "name"=>"photo2011-10-01 08:43:07 +0000.jpg",
       "landlord_viewable"=>"0",
       "attached_file"=>"#<File:0xda0361c>",
       "created_at"=>"1317459424.523741",
       "attachment_type"=>"periodic_check",
       "public"=>"0",
       "room"=>"Kitchen"}}},
 "action"=>"update",
 "id"=>"866",
 "controller"=>"properties"}

Action properties#update

URL http://server.com/000.json

File [GEM_ROOT]/gems/activerecord-2.2.2/lib/active_record/base.rb:2587


It seems clear now that the attribute 0 (after attribute "new_images") is not expected from the server. Seems like it's more of an array position than an attribute.


to do it for one image at a time you need to set the full property key value

[request setPostValue:@"Sink" forKey:@"property[new_images][1][name]"];
[request setPostValue:<timestamp> forKey:@"property[new_images][1][created_at]"];
....

Tedious, but I'm not sure you can set the single key property using an NSDictionary directly. Dont think ASI is that smart.

To do it for an array, just enumerate through your array of images and set the [1] portion of the request key name to the actual index (e.g. [1], [2], [3], etc...)

I think that should work.


ASIHTTPRequest can't automatically do a conversion of an array to a HTTP POST like that.

Try using ASIFormDataRequest instead:

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];

// Upload a file on disk
[request setFile:@"/Users/ben/Desktop/ben.jpg" withFileName:@"myphoto.jpg" andContentType:@"image/jpeg" forKey:@"photo"];

You'll probably have to experiment to some extent to figure out exactly the right format. I've advise using charlesproxy to compare the requests send by your working ruby code and the non-working iOS code on the emulator.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜