Recently I used ASIHTTPRequest to upload images and other data from an iPhone application to a web server. I search around and looked at all the different options and this was best and easiest to use. It’s open source and comes with lots of good examples. I was particularly impressed with the network queue.
The one thing I did not find, was sample code for was posting an image to a server. Here is some sample code:
// Initilize Queue
[networkQueue setUploadProgressDelegate:statusProgressView];
[networkQueue setRequestDidFinishSelector:@selector(imageRequestDidFinish:)];
[networkQueue setQueueDidFinishSelector:@selector(imageQueueDidFinish:)];
[networkQueue setRequestDidFailSelector:@selector(requestDidFail:)];
[networkQueue setShowAccurateProgress:true];
[networkQueue setDelegate:self];
// Initilize Variables
NSURL *url;
ASIFormDataRequest * request;
// Add Image
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory
stringByAppendingPathComponent:@"myImage.jpg"];
// Get Image
NSData *imageData = [[[NSData alloc]
initWithContentsOfFile:dataPath] autorelease];
// Return if there is no image
if(imageData != nil){
url = [NSURL URLWithString:@"http://myserver/upload.php"];
request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"myImageName" forKey:@"name"];
[request setData:imageData forKey:@"file"];
[request setDidFailSelector:@selector(requestWentWrong:)];
[request setTimeOutSeconds:500];
[networkQueue addOperation:request];
queueCount++;
}
[networkQueue go];
Note: It’s not necessary to use a queue here because I’m only uploading 1 thing. But in my application I’m uploading many things and a queue was helpful. It also runs in the asynchronously in the background, which prevents the UI from getting locked up.
Note 2: When sending large files you should use “setFile” instead of “setData”. Files are then read from disk instead of memory. Here is an updated example. Thanks again to Ben Copsey for this library and his useful comments below.
NSString *imagePath = [documentsDirectory
stringByAppendingPathComponent:@"myImage.jpg"];
url = [NSURL URLWithString:@"http://myserver/upload.php"];
ASIFormDataRequest *request =
[[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"myImageName" forKey:@"name"];
[request setFile:imagePath forKey:@"photo"];
More info on streaming here: http://allseeing-i.com/ASIHTTPRequest/How-to-use#streaming
Tags: Apple, Code, iPhone, Mac
If you like this post and would like to receive updates from this blog, please subscribe our feed.
April 8th, 2009 at 5:00 pm
Hi Doug
I’m glad you find ASIHTTPRequest useful!
It’s actually preferable to use a queue even if you only have one request, simply because it’s the easiest way to perform a request in the background. You can create synchronous requests without a queue, but you’ll lock the user interface until the request is complete, unless you want to create and manage threads for the requests yourself.
Ben
April 8th, 2009 at 5:19 pm
Also, if you are uploading several photos at once, use setFile:forKey: rather than setData:forKey:. This way, ASIFormDataRequest will know you’re sending a fair bit of data, and it will stream the request data from a temporary file on disk, which means you don’t need to keep lots of image data in memory.
(See here for more info: http://allseeing-i.com/ASIHTTPRequest/How-to-use#streaming)
Ben
July 30th, 2009 at 12:57 am
Great Example, but your refer to upload.php. Where is the source for upload.php. I have tried several examples of php script, but none work. can you send me or post the PHP script you used in you example.
Thanks
Bill B
January 21st, 2010 at 10:13 pm
Hey Doug & Ben,
I had a quick question. I am using the first ASI queue code to attempt to upload a photo from the iPhone to a PHP based script.
For some reason, all of the $_POST variables are coming in fine, but the $_FILE server variable is coming up blank. There is no record of the images being sent. I’m not sure if there is a problem or if I am just trying to access the information incorrectly on the server side.
Any assistance would be greatly appreciated!!
-Frank
February 18th, 2010 at 8:15 pm
Hey Doug,
What does the PHP end look like to receive the data? I’ve been having a hard time determining why my file uploads won’t work, if it’s because the way I’m sending it or the way it’s being received..
March 8th, 2010 at 9:44 am
Hi Doug and Ben,
Great stuff, I am wondering if it is actually possible to use ASIHTTPRequest to post data from iphone to the Google App Engine’s datastore , and more specifically the google file service https://gae-file-service.appspot.com/
Thanks
Spark
April 12th, 2010 at 8:53 pm
Yeah. Here’s some sample python Google App Engine code with get’s the post data named file.
if (‘file’ in self.request.POST and
self.request.POST.get(‘file’, None) is not None and
self.request.POST.get(‘file’, None).filename):
file_data = self.request.POST.get(‘file’).file.read()
image_length = len(file_data)
if image_length > config.max_size:
self.response.out.write(“IMAGE_TOO_LARGE”)
return
else:
file_content_type = self.request.POST.get(‘file’).type
file_name = self.request.POST.get(‘file’).filename
try:
my_model.image = db.Blob(file_data)
my_model.imageName = file_name
my_model.imageType = file_content_type
my_model.imageLength = image_length
my_model.put()
except Exception, e:
logging.exception(e)
error = ‘Image error processing’
self.response.out.write(‘ERROR_PROCESSING_IMAGE’)
return
logging.info(‘File name : %s’ % file_name)
logging.info(‘Type : %s’ % file_content_type)
logging.info(‘Length : %s’ % image_length)
self.response.out.write(‘SUCCESS’)
class MyModel(db.Model):
image = db.BlobProperty()
imageName = db.StringProperty()
imageType = db.StringProperty()
imageLength = db.IntegerProperty()
May 10th, 2010 at 3:01 pm
if I select an image from the Photo Library, how should I be able to use the setFile ?
June 25th, 2010 at 7:15 pm
How would integrate this using imagePickerController?
would have a code sample?
June 30th, 2010 at 12:42 pm
Hi Frankie,
There is lots of sample code out there for using the imagePicker. Basically you use some code, like I list below to save the image to the iPhone documents directory. Then you can point at this image later to upload it somewhere…
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
NSLog(@”image width: %f image height: %f”, [image size].width, [image size].height);
NSData * imageData = UIImagePNGRepresentation(image);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"myfilename.jpg"];
[imageData writeToFile:dataPath atomically:YES];
[self dismissModalViewControllerAnimated:YES];
}
July 14th, 2010 at 8:52 am
How about uploading images to S3 ?
And if I just want to create another Http Server in iPhone or Mac, are there any samples we can refer to first ?
Thanks
July 14th, 2010 at 3:14 pm
I’m sorry, but I have no experience with Amazon S3.
July 15th, 2010 at 2:13 am
Thanks ! I found that ASIHttpRequest provides some helps for S3. I will check them out.
Another question about back end server. If I just want to write some server using cocoa to do similar thing like “php” did, to receive file from your uploading, is that easy to do ? Sorry I have really no experience on back end service etc.
July 15th, 2010 at 12:39 pm
I’ve never tried that before. What you’d need to do, is write an HTTP Server in cocoa. Here is a simple example:
http://cocoawithlove.com/2009/07/simple-extensible-http-server-in-cocoa.html
November 3rd, 2010 at 9:30 pm
Forrest, ASIHTTPRequest has built-in support for S3.
http://brunofuster.wordpress.com/2010/11/03/uploading-an-image-from-iphone-with-uiimagepicker-and-asihttprequests3/
December 9th, 2010 at 1:19 am
[[[NSData alloc] initWithContentsOfFile:dataPath] autorelease] can be written as [NSData dataWithContentsOfFile:dataPath]