How to upload images in background in iOS?

How can you upload images to a Rails app from an iPhone?

  • I have an iOS app with a Rails back-end. I use carrierwave with Amazon S3 to post images from a webpage to my server. I would like to be able to post images to the server from my iOS app, but am unsure of how to do this. I've made other requests by hitting certain endpoints with the correct parameters as displayed in the Rails console. However, I am unsure how to form this request: Started POST "/images" for 173.22.40.246 at 2012-08-27 18:14:50 +0000 2012-08-27T18:14:50+00:00 app[web.1]: Processing by ImagesController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"1234", "image"=>{"name"=>"", "path"=>#<ActionDispatch::Http::UploadedFile:0x00000004e92830 @original_filename="image.jpeg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"image[path]\"; filename=\"image.jpeg\"\r\nContent-Type: image/jpeg\r\n", @tempfile=#<File:/tmp/RackMultipart20120827-2-1us2x41>>}, "commit"=>"Create Image"} Any help would be greatly appreciated!

  • Answer:

    Alright, with some help from the link provided by James Osborn, I have a working solution. I'm going to best explain what I did so that others can learn from my experience. Here goes: Assuming you have an iPhone app that takes a picture: //handle the image that has just been selected - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { //get the image UIImage* image = [info valueForKey:@"UIImagePickerControllerOriginalImage"]; //scale and rotate so you're not sending a sideways image -> method provided by http://blog.logichigh.com/2008/06/05/uiimage-fix/ image = [self scaleAndRotateImage:image]; //obtain the jpeg data (.1 is quicker to send, i found it better for testing) NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, .1)]; //get the data into a string NSString* imageString = [NSString stringWithFormat:@"%@", imageData]; //remove whitespace from the string imageString = [imageString stringByReplacingOccurrencesOfString:@" " withString:@""]; //remove < and > from string imageString = [imageString substringWithRange:NSMakeRange(1, [imageString length]-2)]; self.view.hidden = YES; //dismissed the camera [picker dismissModalViewControllerAnimated:YES]; //posts the image [self performSelectorInBackground:@selector(postImage:) withObject:imageString]; } - (void)postImage:(NSString*)imageData { //image string formatted in json NSString* imageString = [NSString stringWithFormat:@"{\"image\": \"%@\", \"authenticity_token\": \"\", \"utf8\": \"✓\"}", imageData]; //encoded json string NSData* data = [imageString dataUsingEncoding:NSUTF8StringEncoding]; //post the image [API postImage:data]; } Then for the post: +(NSArray*)postImage:(NSData*) data { //url that you're going to send the image to NSString* url = @"www.yoururl.com/images"; //pretty self explanatory request building NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]]; [request setTimeoutInterval:10000]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPMethod: @"POST"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setHTTPBody:data]; NSError *requestError; NSURLResponse *urlResponse = nil; NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError]; return [API generateArrayWithData:result]; } On the rails side I set up a method specifically for handling mobile images, this should help you post the image to your Amazon S3 account through Carrierwave: def post respond_to do |format| format.json { #create a new image so that you can call it's class method (a bit hacky, i know) @image = Image.new #get the json image data pixels = params[:image] #convert it from hex to binary pixels = @image.hex_to_string(pixels) #create it as a file data = StringIO.new(pixels) #set file types data.class.class_eval { attr_accessor :original_filename, :content_type } data.original_filename = "test1.jpeg" data.content_type = "image/jpeg" #set the image id, had some weird behavior when i didn't @image.id = Image.count + 1 #upload the data to Amazon S3 @image.upload(data) #save the image if @image.save! render :nothing => true end } end end This works for me for posting and I feel should be pretty extendable. For the class methods: #stores the file def upload(file) self.path.store!(file) end #converts the data from hex to a string -> found code here http://4thmouse.com/index.php/2008/02/18/converting-hex-to-binary-in-4-languages/ def hex_to_string(hex) temp = hex.gsub("\s", ""); ret = [] (0...temp.size()/2).each{|index| ret[index] = [temp[index*2, 2]].pack("H2")} file = String.new ret.each { |x| file << x} file end Not saying this code is perfect, not even by a longshot. However, it does work for me. I'm open to suggestions if anyone thinks it could be improved. Hope this helps!

Nick Schulze at Quora Visit the source

Was this solution helpful to you?

Other answers

Hi, I faced a similar problem recently. This article was really helpful: http://brainbowapps.com/articles/2010/uploading-files-from-iphone-to-rails.html You should also know that in iOS6 you will be able to select camera-roll images from mobile safari (meaning you could just pass users to a mobile rendered 'upload' page on your rails app, and avoid some of the complication). Hope this helps, Good Luck!

James Osborn

Maybe carrierwave-iOS,  an easy-to-use open source iOS library which provides a flexible way to download, upload and edit asset files will help you?: https://netguru.co/blog/carrierwave-ios-in-open-source

Ania Banaszek

Related Q & A:

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.