NSURLConnection to upload file asynchonrously? - objective-c

I'm kinda of new at ios development,
I've been reading and searching but cannot find a working example or an example of
how to upload a file from iphone to webserver asychronously..
I'm able to upload synchronously using
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
it works, but it blocks my main thread.
NSUrlConnection has this delegate (connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:)
but I've no idea how to implement it.
Can someone please point me in the right direction?

I have managed to get uploading to work with NSURLConnection asynchronously with this:
-(NSURLRequest *)postRequestWithURL: (NSString *)url
data: (NSData *)data
fileName: (NSString*)fileName
{
// from http://www.cocoadev.com/index.pl?HTTPFileUpload
//NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
NSMutableURLRequest *urlRequest = [[[NSMutableURLRequest alloc] init] autorelease];
[urlRequest setURL:[NSURL URLWithString:url]];
//[urlRequest setURL:url];
[urlRequest setHTTPMethod:#"POST"];
NSString *myboundary = [NSString stringWithString:#"---------------------------14737809831466499882746641449"];
NSString *contentType = [NSString stringWithFormat:#"multipart/form-data; boundary=%#",myboundary];
[urlRequest addValue:contentType forHTTPHeaderField: #"Content-Type"];
//[urlRequest addValue: [NSString stringWithFormat:#"multipart/form-data; boundary=%#", boundry] forHTTPHeaderField:#"Content-Type"];
NSMutableData *postData = [NSMutableData data]; //[NSMutableData dataWithCapacity:[data length] + 512];
[postData appendData:[[NSString stringWithFormat:#"\r\n--%#\r\n", myboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[[NSString stringWithFormat:#"Content-Disposition: form-data; name=\"userfile\"; filename=\"%#\"\r\n", fileName]dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[[NSString stringWithString:#"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[NSData dataWithData:data]];
[postData appendData:[[NSString stringWithFormat:#"\r\n--%#--\r\n", myboundary] dataUsingEncoding:NSUTF8StringEncoding]];
[urlRequest setHTTPBody:postData];
return urlRequest;
}
usage is as follows:
NSURLRequest *urlRequest = [self postRequestWithURL:urlString
data:aVideo.msgvid
fileName:filename];
uploadConnection =[[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];

Threading is not necessary for this kind of problem. I would suggest you use the asynchronous functionality built into NSURLConnection:
NSURLConnection *connection = [NSURLConnection initWithRequest:request delegate:self];
[connection start];
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Get your response, do stuff
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//Show error, retry, etc
}
EDIT: If you are really looking to upload a file and want to display a progress bar, then you should look at ASIHTTPRequest framework, which you can find more info on here: http://allseeing-i.com/ASIHTTPRequest/
For uploading a POST request with data using ASIHTTPRequest, you would do:
NSURL *url = [NSURL URLWithString:#"YOUR_URL_HERE"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"123" forKey:#"user_id"];
[request setData:someData withFileName:#"someData.jpg" andContentType:#"image/png" forKey:#"image"];
[request setProgressDelegate:self];
[request setDelegate:self];
[request startAsynchronous];
Again, refer to the link above for the framework and documentation. I highly recommend it.

You cant create new thread for that task:
[NSThread detachNewThreadSelector:#selector(upload:) toTarget:self withObject:data];
And when you will finish uploading, just call some implemented method in your main thread (for example uploaded):
[self performSelectorOnMainThread:#selector(uploaded) withObject:nil waitUntilDone:NO];

Related

How to send HTTP POST request to PHP service with Objective-C

Im trying to post to php and get the response. The php file has an echo "hello" which should just print hello. I'm trying to test to see if posting is working but in my error log the NSlog doesn't display anything:
#interface ViewController ()
#end
#implementation ViewController
#synthesize email, password,receivedData;
-(IBAction)Login:(id)sender{
// Create the request.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://grouporder.site90.net/test.php"]];
// Specify that it will be a POST request
request.HTTPMethod = #"POST";
// This is how we set header fields
[request setValue:#"application/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
// Convert your data and set your request's HTTPBody property
NSString *stringData = [NSString stringWithFormat:#"%#", email];
NSData *requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;
// Create url connection and fire request
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data
{
[receivedData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//initialize convert the received data to string with UTF8 encoding
NSString *htmlSTR = [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"%#" , htmlSTR);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"%#" , error);
}
Since you did not mention about what kind of body type you want to use this example shows you how to post multipart/form-data request.
-(NSString *)generateRandomBoundryString {
CFUUIDRef UUID = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef UUIDString = CFUUIDCreateString(kCFAllocatorDefault,UUID);
NSString *aNSString = (__bridge NSString *)UUIDString;
CFRelease(UUID);
CFRelease(UUIDString);
return aNSString;
}
-(IBAction)Login:(id)sender {
NSString *bndry = [self generateRandomBoundryString];
NSString *contentType = [[NSString alloc] initWithString:[NSString stringWithFormat:#"multipart/form-data; boundary=%#", bndry]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://grouporder.site90.net/test.php"]];
[request setHTTPMethod:#"POST"];
[request setValue: contentType forHTTPHeaderField:#"Content-Type"];
//form-data block
NSMutableData *requestBody = [NSMutableData data];
[requestBody appendData:[[NSString stringWithFormat:#"\r\n--%#\r\n", bndry] dataUsingEncoding:NSUTF8StringEncoding]];
[requestBody appendData:[[NSString stringWithFormat:#"%#=%#", #"name", #"John"] dataUsingEncoding:NSUTF8StringEncoding]];
[requestBody appendData:[[NSString stringWithFormat:#"\r\n--%#\r\n", bndry] dataUsingEncoding:NSUTF8StringEncoding]];
[requestBody appendData:[[NSString stringWithFormat:#"%#=%#", #"password", #"myPassword"] dataUsingEncoding:NSUTF8StringEncoding]];
[requestBody appendData:[[NSString stringWithFormat:#"\r\n--%#\r\n", bndry] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:requestBody];
//form-data block
// NSURLConnection Asynchronous Block
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *rspreportStatus, NSData *datareportStatus, NSError *e)
{
if (e == nil)
{
// If all ok you can processes response data here.
}
else {
NSLog(#"%#", e.localizedDescription);
}
}];
}
If body is application/x-www-form-urlencoded you should change Content-Type value like this.
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
and replace //form-data block block with this.
[requestBody appendData:[[NSString stringWithFormat:#"name=%#&password=%#", #"John", #"myPassword"] dataUsingEncoding:NSUTF8StringEncoding]];
#"John" and #"myPassword" has to be URL encoded.

Post data on web server with web service

Hello I am tying to save data on web server with a web service implemented in PHP.
I am trying below code to do it. I am getting response from server but the data is not getting saved to server. I have wasted 5-6 hours of the day in googling and trying code given on net. But nothing seems to work :(
NSDictionary *someInfo = [NSDictionary dictionaryWithObjectsAndKeys:
txtTreasureName.text, #"name",
txtDescription.text, #"description",
txtMaterials.text, #"materials",
#"77.3833", #"longitude",
#"29.0167", #"latitude",
categoryIdStr, #"categoryId",
nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:treasureInfo
options:NSJSONWritingPrettyPrinted
error:&error];
if (! jsonData) {
DLog(#"Got an error: %#", error);
} else {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSString *urlString = #"http://www.myurl.php";
NSURL *url = [NSURL URLWithString:urlString];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json"
forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json"
forHTTPHeaderField:#"Accept"];
[request setValue:[NSString stringWithFormat:#"%d",
[jsonData length]]
forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:jsonData];
DLog(#"%#", request);
[[NSURLConnection alloc]
initWithRequest:request
delegate:self];
// Print json
DLog(#"JSON summary: %#", [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding]);
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *error) {
if ([data length] &&
error == nil) {
DLog(#"%#", [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding]);
if ([self shouldDismiss]) {
[self dismissViewControllerAnimated:YES
completion:nil];
}
}
}];
}
Set Request URL in the function,
You have alread y created data Dictionary
NSDictionary *someInfo = [NSDictionary dictionaryWithObjectsAndKeys:
txtTreasureName.text, #"name",
txtDescription.text, #"description",
txtMaterials.text, #"materials",
#"77.3833", #"longitude",
#"29.0167", #"latitude",
categoryIdStr, #"categoryId",
nil];
Add this function to your implementation file and invoke it, rest will be dont by this function
[self postWith:someInfo];
Add this
- (void)postWith:(NSDictionary *)post_vars
{
#warning Add your Webservice URL here
NSString *urlString = [NSString stringWithFormat:#"YourHostString"];
NSURL *url = [NSURL URLWithString:urlString];
NSString *boundary = #"----1010101010";
// define content type and add Body Boundry
NSString *contentType = [NSString stringWithFormat:#"multipart/form-data; boundary=%#",boundary];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request addValue:contentType forHTTPHeaderField: #"Content-Type"];
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:#"--%#\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
NSEnumerator *enumerator = [post_vars keyEnumerator];
NSString *key;
NSString *value;
NSString *content_disposition;
while ((key = (NSString *)[enumerator nextObject])) {
value = (NSString *)[post_vars objectForKey:key];
content_disposition = [NSString stringWithFormat:#"Content-Disposition: form-data; name=\"%#\"\r\n\r\n", key];
[body appendData:[content_disposition dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[value dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:#"\r\n--%#\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
}
//Close the request body with Boundry
[body appendData:[[NSString stringWithFormat:#"\r\n--%#--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
[request addValue:[NSString stringWithFormat:#"%d", body.length] forHTTPHeaderField: #"Content-Length"];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(#"%#", returnString);
}

NSMutableURLRequest setHTTPBody method crashes App with SIGABRT Warning

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"riderfinder.appspot.com/login"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/plain"
forHTTPHeaderField:#"Content-type"];
NSString *body = #"username=";
[body stringByAppendingString:accountEntered];
[body stringByAppendingString:#"&"];
[body stringByAppendingString:#"password="];
[body stringByAppendingString:passwordEntered];
NSMutableData *data = [[NSMutableData data] initWithString:body];
//Crashes everything with "SIGABRT" warning/error. Nothing else is said.
[request setHTTPBody:data];
I would appreciate it if anyone has any idea what is going wrong. I narrowed it down to the last line causing the crash through Apple's debugger. Thank you very much!
There are 2 errors:
body is not appended, [body stringByAppendingString:accountEntered] should be body=[body stringByAppendingString:accountEntered]
NSMutableData *data = [[NSMutableData data] initWithString:body]; is not correct used,you can use NSData *data=[body dataUsingEncoding:NSUTF8StringEncoding];
so i modified the code:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"riderfinder.appspot.com/login"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/plain" forHTTPHeaderField:#"Content-type"];
NSString *body = #"username=";
body=[body stringByAppendingString:accountEntered];
body=[body stringByAppendingString:#"&"];
body=[body stringByAppendingString:#"password="];
body=[body stringByAppendingString: passwordEntered];
//NSMutableData *data = [[NSMutableData data] initWithString:body];
NSData *data=[body dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
First,you should make 'accountEntered' and 'passwordEntered' not nil.
If you have done that,you should set breakpoint to know exactly which line crashes.Usually, "SIGABRT" error means you release more or unrecogized selector .
The code on answer 1 is right.

iOS YouTube Video Upload Error

I am trying to upload a video using Objective-C and YouTube API but it is not working and return error at last step. The error reads "User authentication required".
I am following this API document specifically the one which is without metadata. I got the authentication token with ClientLogin API
I checked authentication token with NSLog and it's there. I see the upload API also returns Upload URL but when I send HTTP PUT request to retrieved Upload URL, it returns an error mentioned above.
Here's Upload Code
- (bool) upload:(NSString *)file {
NSData *fileData = [NSData dataWithContentsOfFile:file];
NSURL *url = [NSURL URLWithString:self.UploadURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"PUT"];
[request setValue:#"Content-Type" forHTTPHeaderField:#"application/octet-stream"];
[request setValue:#"Content-Length" forHTTPHeaderField:[NSString stringWithFormat:#"%ud", [fileData length]]];
[request setHTTPBody:fileData];
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
NSLog(#"%#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
if (response == nil) {
return NO;
} else {
return YES;
}
}
I also tried the Direct Upload method but this always gives me Invalid Request error. Below is the code.
- (bool) directUpload:(NSString *)file {
NSString *title = [file lastPathComponent];
NSString *desc = #"This is test video.";
NSString *category = #"People";
NSString *keywords = #"video";
NSString *boundary = #"--qwerty";
NSString *xml = [NSString stringWithFormat:
#"<?xml version=\"1.0\"?>"
#"<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:media=\"http://search.yahoo.com/mrss/\" xmlns:yt=\"http://gdata.youtube.com/schemas/2007\">"
#"<media:group>"
#"<media:title type=\"plain\">%#</media:title>"
#"<media:description type=\"plain\">%#</media:description>"
#"<media:category scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">%#</media:category>"
#"<media:keywords>%#</media:keywords>"
#"</media:group>"
#"</entry>", title, desc, category, keywords];
NSData *fileData = [NSData dataWithContentsOfFile:file];
NSMutableData *postBody = [NSMutableData data];
[postBody appendData:[[NSString stringWithFormat:#"%#\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:#"Content-Type: application/atom+xml; charset=UTF-8\n\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:#"%#\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:#"Content-Type: video/mp4\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:#"Content-Transfer-Encoding: binary\n\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:fileData];
[postBody appendData:[[NSString stringWithFormat:#"%#", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
NSURL *url = [NSURL URLWithString:#"http://uploads.gdata.youtube.com/feeds/api/users/default/uploads"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"GoogleLogin auth=\"%#\"", self.AuthToken] forHTTPHeaderField:#"Authorization"];
[request setValue:#"2" forHTTPHeaderField:#"GData-Version"];
[request setValue:[NSString stringWithFormat:#"key=%#", self.DeveloperKey] forHTTPHeaderField:#"X-GData-Key"];
[request setValue:[file lastPathComponent] forHTTPHeaderField:#"Slug"];
[request setValue:[NSString stringWithFormat:#"multipart/related; boundary=\"%#\"", boundary] forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%ud", [postBody length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"close" forHTTPHeaderField:#"Connection"];
[request setHTTPBody:postBody];
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
NSLog(#"%#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
if (response == nil) {
return NO;
} else {
return YES;
}
}
i think you should check this :-
https://developers.google.com/youtube/2.0/developers_guide_protocol_video_feeds
and you also check this :-
http://urinieto.com/2010/10/upload-videos-to-youtube-with-iphone-custom-app/

NSImage from NSPasteBoard to base64 for HTTP POST not working as expected

I'm playing around with trying to create a little menu item app to learn Cocoa/OS X programming.
Basically it's something that sits in your dock, you drag an image file to it, and it will upload the file to imgur and tell you the URL it was uploaded to.
It "works" in that imgur's API doesn't throw any errors back at me, but the images don't render properly either.
Applicable code:
ScreenshotController.m
- (void)uploadImage:(NSImage *)image
{
NSData *imageData = [image TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
imageData = [imageRep representationUsingType:NSPNGFileType properties:nil];
NSString *base64 = [imageData encodeBase64WithNewlines: NO];
NSString *jsonRequest = #"key=92428d1a5839df89cb8e87e8a31cd935&image=";
jsonRequest = [jsonRequest stringByAppendingString:[base64 stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
NSLog(#"Request: %#", jsonRequest);
NSData *requestData = [NSData dataWithBytes: [jsonRequest UTF8String] length: [jsonRequest length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: #"http://api.imgur.com/2/upload"]];
[request setHTTPMethod: #"POST"];
[request setHTTPBody: requestData];
NSData *returnData = [ NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil ];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(#"Returned Json: %#", returnString);
}
StatusItemView.m
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSArray *dragTypes = [NSArray arrayWithObjects:NSURLPboardType, NSFileContentsPboardType, NSFilenamesPboardType, nil];
[self registerForDraggedTypes:dragTypes];
}
return self;
}
//perform the drag and log the files that are dropped
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
NSPasteboard *pb = [sender draggingPasteboard];
if([[pb pasteboardItems] count] != 1){
return NO;
}
if([NSBitmapImageRep canInitWithPasteboard:pb]){
NSImage *image = [[NSImage alloc] initWithPasteboard:pb];
[[[ScreenshotController alloc] autorelease] uploadImage:image];
return YES;
}
return NO;
}
Here is an example image it uploaded to imgur, so you can see what I mean: http://imgur.com/6pLgG (the source file was a perfectly normal PNG).
Complete source code is here if you need to see anything else: https://github.com/zbuc/imgur
So I figured out a way to upload to the anon api, I hope this helps out.
- (void)uploadImageToImgur{
NSData *_imageData = UIImageJPEGRepresentation(image,90);
NSString *urlString = #"http://api.imgur.com/2/upload.json";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"POST"];
NSMutableData *body = [NSMutableData data];
NSString *boundary = #"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:#"multipart/form-data; boundary=%#", boundary];
[request addValue:contentType forHTTPHeaderField:#"Content-Type"];
// file
[body appendData:[[NSString stringWithFormat:#"--%#\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[#"Content-Disposition: attachment; name=\"image\"; filename=\".tiff\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[#"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:_imageData]];
[body appendData:[#"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// text parameter
[body appendData:[[NSString stringWithFormat:#"--%#\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:#"Content-Disposition: form-data; name=\"key\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
//Set API key
[body appendData:[#"API_STRING_HERE" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[#"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// close form
[body appendData:[[NSString stringWithFormat:#"--%#--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// set request body
[request setHTTPBody:body];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSArray *decodedResponse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSString *imgurUrlString = [[[decodedResponse valueForKey:#"upload"] valueForKey:#"links"] valueForKey:#"imgur_page"];
[self uploadToImgurCompleteWithUrlString:imgurUrlString];
}];
}