2

Hi everyone and thanks in advance for any help providing in understanding in how to convert some NSURLConnection code into the newer NSURLSession. What I am trying to do is to make a POST request to a server, and send a photo base 64 encoded for the key "photo".

Below I have an working example written in NSURLConnection and I will like to convert it into NSURLSession.

As I read on the apple documentation from what I understood I should use a Data tasks because in my case it is an image and if it is a larger transfer like a video the I should use Upload tasks.

Regarding the upload task I have found the next tutorial but the problem is that in my case I also set a headers and also my content type should be multipart/form-data.

NSURL *url = [NSURL URLWithString:myLink];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

    [request setHTTPMethod:@"POST"];

    [request addValue:parameter1 forHTTPHeaderField:header1];
    [request addValue:parameter2 forHTTPHeaderField:header2];
    [request addValue:parameter3 forHTTPHeaderField:header3];
    [request addValue:parameter4 forHTTPHeaderField:header4];
    [request addValue:parameter5 forHTTPHeaderField:header5];

    [request setHTTPBody:[UIImageJPEGRepresentation(avatarImage, 1.0) base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength]];

    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){

                               NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;

                               NSError *jsonError;

                               if(httpResp.statusCode == 200){
                                   NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
                                                                                        options:NSJSONReadingAllowFragments
                                                                                          error:&error];


                                   if (!jsonError) {

                                       [[NSUserDefaults standardUserDefaults] setObject:[dict objectForKey:@"photo_url"] forKey:@"avatarLink"];
                                       [[NSUserDefaults standardUserDefaults] synchronize];

                                   }


                               }
                               else {

                                   NSString *errorCode = [NSString stringWithFormat:@"An error has occured while uploading the avatar: %ld", (long)httpResp.statusCode];
                                   [GeneralUse showAlertViewWithMessage:errorCode andTitle:@"Error"];

                               }


                           }];

I will like to mention that I tried to build an working example using Ray Wenderlich tutorial but I was getting an error regarding the way I was setting my headers

Thank you in advance for any provided help!

Laur Stefan
  • 1,871
  • 3
  • 20
  • 49
  • 1. You say the code sample will "send a photo base 64 encoded for the key 'photo'". No, this code sample isn't using the `photo` key. Do you want to use the `photo` key or not? 2. When using `NSURLSession` the process is largely the same. Build the `NSMutableURLRequest` and issue it. If using data task, you specify the body in the request like above. If using upload task, you don't specify the body in the request, but rather supply it as a parameter to `uploadTaskWithRequest` method. 3. Why not use `multipart/form-data` request (http://stackoverflow.com/questions/26162616) – Rob Jul 12 '15 at 00:05

1 Answers1

1

I'm using a simple HTTPClient class I wrote, but unfortunately it currently does not support upload tasks. But below I propose a method for creating such an upload task. My client maintains a reference to an NSURLSession and a dictionary of running tasks (key is the task itself, value is the NSData received) as a way of asynchronously handling reception of response data for (possibly more than one) session tasks. In order to work my client implements the following protocols: . I would create the upload task as follows:

- (NSURLSessionTask *) startUploadTaskForURL: (NSURL *) url withData: (NSData *) data {
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  [request setHTTPMethod:@"POST"];
  [request addValue:@"multipart/form-data" forHTTPHeaderField:@"Content-Type"];
  NSURLSessionUploadTask uploadTask = [self.session uploadTaskWithRequest:request fromData:data];
  [self scheduleTask:task];
  return task;
}

- (void) scheduleTask: (NSURLSessionTask *) task {
    [self.runningTasks setObject:[NSMutableData data] forKey:task];
    [task resume];
}

- (NSMutableData *) dataForTask: (NSURLSessionTask *) task {
    return [self.runningTasks objectForKey:task];
}

- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"HTTPClient: Data task received data: %@", dataString);
    NSMutableData *runningData = [self dataForTask:dataTask];
    if (!runningData) {
        NSLog(@"No data found for task");
    }
    [runningData appendData: data];
}

- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    NSLog(@"HTTPClient: Task completed with error: %@", error);
    // my client also works with a delegate, so as to make it reusable
    [self.delegate sessionTask:task completedWithError:error data:[self dataForTask:task]];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
    NSLog(@"HTTPClient: did send body data: %lld of %lld bytes ", totalBytesSent, totalBytesExpectedToSend);
}
Rudi Angela
  • 1,391
  • 1
  • 12
  • 19