Uploading Files from iPhone
We recently completed an iPhone application that allows user to, among other things, perform voice-recording and upload the recorded file to a server. For uploading, it uses HTTP multipart POST against an Apache webserver. This type of arrangement is a very common way of sending a file to a webserver. I am certain that similar implementations can be found in several different programming languages. Here is my Objective C implementation…I tried to focus on brevity and encapsulation.
The code:
/**
* Upload a file to a webserver thru http post.
* uid is the http request id
* requestData is list of key/value pairs to be sent along with the file
* url is the destination url
* filePath is absolute file path of the file to be uploaded
*/
- (void)postUpload:(NSString *)url
:(NSString *)uid
:(NSDictionary *)requestData
:(NSString *)filePath
{
NSURL *theURL = [NSURL URLWithString:url];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:theURL
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:20.0f];
[theRequest setHTTPMethod:@"POST"];
[theRequest setValue:uid forHTTPHeaderField:@"uid"];
// define post boundary...
NSString *boundary = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *boundaryString = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[theRequest addValue:boundaryString forHTTPHeaderField:@"Content-Type"];
// define boundary separator...
NSString *boundarySeparator = [NSString stringWithFormat:@"--%@\r\n", boundary];
//adding the body...
NSMutableData *postBody = [NSMutableData data];
// adding params...
for (id key in requestData) {
NSString *formDataName = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key];
NSString *formDataValue = [NSString stringWithFormat:@"%@\r\n", [requestData objectForKey:key]];
[postBody appendData:[boundarySeparator dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[formDataName dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[formDataValue dataUsingEncoding:NSUTF8StringEncoding]];
}
// if file is defined, upload it...
if (filePath) {
NSArray *split = [filePath componentsSeparatedByString:@"/"];
NSString *fileName = (NSString*)[split lastObject];
NSData *fileContent = [NSData dataWithContentsOfFile:filePath options:0 error:nil];
[postBody appendData:[boundarySeparator dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"audioBody\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"Content-Type: application/octet-stream\r\n\r\n"
dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:fileContent];
}
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r \n",boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
[theRequest setHTTPBody:postBody];
NSURLResponse *theResponse = NULL;
NSError *theError = NULL;
NSData *reqResults = [NSURLConnection sendSynchronousRequest:theRequest
returningResponse:&theResponse
error:&theError];
if (!reqResults) {
NSLog(@"Connection error for URL: %@", [url description]);
UIAlertView *alert = [UIAlertView alloc];
[[alert initWithTitle:@"Error in connection"
message:[theError localizedDescription]
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"Quit", nil] autorelease];
[alert show];
}
}
Here’s an example of how you can use this method:
NSArray *keys =[NSArrayarrayWithObjects:@"recipients", @"title", @"textBody", nil];
NSArray *objects = [NSArray arrayWithObjects:uids, inputSubject.text, inputMessage.text, nil];
NSDictionary* postData = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
// post now…
[[WebServicealloc] postUpload:URL_ENDPOINT_SEND_MESSAGE
:appDelegate.uid
:postData
:[recorder recordFilePath]];
URL_ENDPOINT_SEND_MESSAGE is set to the URL that can receive a multipart POST. To test this out, I have quickly written the following PHP code.
<?php
define(‘FILE_SAVE_DIRECTORY’,‘/folder/to/save/uploaded/files/’);
error_log(“Requesting upload file….”);
error_log(print_r($_SERVER, true));
error_log(“\n\n”);
error_log(print_r($_FILES, true));
if ($_POST && isset($_FILES['file'])) {
error_log(“ the file:….” . $_FILES['file']['name']);
$file = $_FILES['file'];
$dst = FILE_SAVE_DIRECTORY . basename($file['name']);
if (move_uploaded_file($file['tmp_name'], $dst)){
echo ‘Upload Successfully: ‘.$dst;
}
else {
echo ‘Error uploading the file.’;
}
}
?>
Put this code in your php-enabled webserver. Then, set URL_ENDPOINT_SEND_MESSAGE to point to the script.
It’s that simple. Now you’re ready to use HTTP upload in your next iPhone project.

This tutorial is if you want your iPhone app to be a web server able to receive files via HTTP from a desktop computer?