使用NSURLSession

时间:2015-05-23 04:51:00

标签: ios objective-c nsurlsession

iOS开发的全新,所以我在这里感觉有些迷失。我们如何使用NSURLSession将图像上传到Web服务器(我将设置的PHP rest API)?

我已经能够将代码编写到用户能够选择图像的位置,但现在我需要将此图像发送到我的PHP网页来处理它。有关如何执行此操作的任何建议,以及让我的PHP设置来处理此类请求的最佳方法吗?

任何建议/见解将不胜感激!

2 个答案:

答案 0 :(得分:0)

在与Web服务交互时使用的Abetter选择是AFNetworking

以下是上传图片的代码

-(void)uploadImage:(UIImage *)image{
    AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:@"http://server.url"]];
    NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
    NSDictionary *parameters = @{}; // pass parameter here
    AFHTTPRequestOperation *op = [manager POST:@"{SERVER_URL}" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        //do not put image inside parameters dictionary as I did, but append it!
        [formData appendPartWithFileData:imageData name:paramNameForImage fileName:@"photo.jpg" mimeType:@"image/jpeg"];
    } success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"Success: %@ \n%@", operation.responseString, responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@ \n%@", operation.responseString, error);
    }];
    [op start];
}

答案 1 :(得分:0)

NSURLSession与NSURLSessionTasks一起使用,它执行实际的HTTP调用。这些任务以异步方式工作并以块的形式提供数据,因此您需要一些对象来设置这些任务,使它们工作并等待其结果。此对象的类需要充当NSURLSessionTasks的委托,因此需要实现一些委托协议:

@interface MyUrlSessionTasksManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
...
@end

我有一个班级可以做到这一点。它保留了正在运行的任务列表,并累积了检索到的分块数据,直到它们完成为止。然后它将结果返回给请求者,从技术上讲,它是委托者。在初始化时,它创建并配置NSURLSession(我正在使用cookie)和一个空的任务列表:

- (id) init {
    self = [super init];
    if (self) {
        self.runningTasks = [NSMutableDictionary dictionary];
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        configuration.HTTPShouldSetCookies = YES;
        configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
        self.session = [NSURLSession sessionWithConfiguration: configuration
                                                     delegate: self
                                                delegateQueue: [NSOperationQueue mainQueue]];
    }
    return self;
}

如上所述,此类适用于报告完成结果的委托。以下是委托的定义:

@protocol MyUrlSessionTasksManagerDelegate <NSObject>
- (void) sessionTask: (NSURLSessionTask *) task completedWithError: (NSError *) error data: (NSData *) data;
@end

此类的主要方法(对于本例)是:

- (NSURLSessionTask *) startPostTaskForURL: (NSURL *) url parameters: (NSDictionary *) values {
    NSURLRequest *request = [self createPostRequestWithURL:url parameters:values];
    NSURLSessionTask *task = [self.session dataTaskWithRequest:request];
    [self scheduleTask:task];
    return task;
}

此方法采用NSURL和参数的NSDictionary,创建HTTP POST请求,使用该请求创建任务并安排任务执行。调度只是将任务放在字典“运行任务”中。使用关联的Data对象来累积收到的数据:

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

每当有任务数据时,都会调用以下TaskDelegate方法。它所做的就是在运行任务列表中查找任务,并将收到的数据附加到与Data对象相关的任务中:

- (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    NSMutableData *runningData = [self dataForTask:dataTask];
    if (!runningData) {
        NSLog(@"No data found for task");
    }
    [runningData appendData: data];
}

完成数据接收后,将调用以下TaskDelegate方法。它只是报告给它的委托,传递整个Data对象和任何错误:

- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    [self.delegate sessionTask:task completedWithError:error data:[self dataForTask:task]];
}

使用了一些内部支持方法:

- (NSMutableData *) dataForTask: (NSURLSessionTask *) task {
    return [self.runningTasks objectForKey:task];
}
- (NSString *)urlEncodedUTF8String: (NSString *) source {
    return (id)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(0, (CFStringRef)source, 0,
                                                       (CFStringRef)@";/?:@&=$+{}<>,", kCFStringEncodingUTF8));
}

- (NSString *) createHttpParameters: (NSDictionary *) parameters {
    NSMutableString *body = [NSMutableString string];
    for (NSString *key in parameters) {
        NSString *val = [parameters objectForKey:key];
        if ([body length])
            [body appendString:@"&"];
        [body appendFormat:@"%@=%@", [self urlEncodedUTF8String: [key description]],
         [self urlEncodedUTF8String: [val description]]];
    }
    return body;
}

- (NSURLRequest *)createPostRequestWithURL:(NSURL *)url
                          parameters:(NSDictionary *)parameters {

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];
    [request addValue:@"application/x-www-form-urlencoded"
   forHTTPHeaderField:@"Content-Type"];
    NSString * httpParams = [self createHttpParameters:parameters];

    [request setHTTPBody:[httpParams dataUsingEncoding:NSUTF8StringEncoding]];
    return request;
}

此代码中未提供的是如何获取文件并将其转换为正确的编码,以将其作为POST主体中的参数传递。原因是这个代码是从我的一个项目中复制的,它没有使用文件上传。我仍然希望它可以帮到你。