将NSURLConnection转换为NSURLSessionUploadTask示例

问题描述:

大家好,感谢您提前了解如何将一些NSURLConnection代码转换为更新的NSURLSession。
我要做的是向服务器发出POST请求,并为密钥photo发送64位照片库。

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".

我有一个用NSURLConnection编写的工作示例,我想将其转换为NSURLSession。

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.

关于上传任务,我找到了下一个教程但问题是在我的情况下我也设置了标题,我的内容类型也应该是multipart / form-data。

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"];

                               }


                           }];

我想提一下,我尝试使用Ray Wenderlich教程构建一个工作示例,但我得到了关于我设置标题的方式的错误

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!

我正在使用我写的一个简单的HTTPClient类,但不幸的是它目前不支持上传任务。但是下面我提出了一种创建这种上传任务的方法。我的客户端维护对NSURLSession的引用和运行任务的字典(键是任务本身,值是接收到的NSData),作为异步处理(可能多于一个)会话任务的响应数据接收的方式。为了工作,我的客户端实现了以下协议:。
我将创建上传任务,如下所示:

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);
}