等待多部分图像发送完成

时间:2013-11-21 14:55:40

标签: ios afnetworking grand-central-dispatch multipartform-data

我在iOS7中使用应用程序,它是一种社交网络应用程序,其中包含带有图像的帖子和后端,可以保存从客户端发送的所有数据。 iOS客户端通过json发送帖子的信息,在发送信息后,它开始使用AFNetworking通过多部分表单发送图像。

我需要在发送图片时收到通知,以便我可以使用新帖子刷新应用程序的主视图,包括客户最近发布的帖子。在实践中,如果我请求后端的最后一个帖子并且多部分尚未完成,则图像的发送会被干扰并且无法发送图像。

后端是在WCF中开发的,是一个RESTful JSON Web服务。

以下是将帖子发送到后端的方法:

+(void)addPostToServerAddtext:(NSString *)text addimage:(UIImage *)image addbeach:(NSString *)beach location:(NSString*)location;
{
    NSLog(@"entro a addPost");
    NSString *urlBackend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"URLBackend"];

    NSData* dataImage = UIImageJPEGRepresentation(image, 1.0);
    NSString* ImageName = [NSString stringWithFormat:@"%@_%@.jpg",idUser ,dateToServer];
    NSString *jsonRequest = [NSString stringWithFormat:@"{\"Date\":\"%@\"...."];

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@newPost",urlBackend]];

    NSMutableURLRequest *request = [ [NSMutableURLRequest alloc] initWithURL:url];
    NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];

    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:requestData];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    [connection start];

    if (image != nil) {

        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        [manager POST:[NSString stringWithFormat:@"%@FileUpload",urlBackend]
           parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
            [formData appendPartWithFileData:dataImage name:@"image" fileName:ImageName mimeType:@"image/jpg" ];
        }
              success:^(AFHTTPRequestOperation *operation, id responseObject) {
            NSLog(@"Success: %@", responseObject);
        }
              failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Error: %@", error);
        }];
    }
}

1 个答案:

答案 0 :(得分:1)

有几点想法:

  1. 你说:

      

    iOS客户端通过json发送帖子的信息,在发送信息后,它开始使用AFNetworking通过多部分表单发送图像。

    从技术上讲,您不是在等待发送信息,而是在同时执行这些信息。你想要这些并发吗?还是顺序?或者为什么不只是发布信息和图像的单个请求?

  2. 我建议将AFNetworking用于这两个请求。你有一个强大的框架来管理网络请求,在那里看到毛茸茸的NSURLConnection代码感觉很尴尬。

    如果您保留NSURLConnection代码,请注意您希望start NSURLConnection,除非您使用initWithRequest:delegate:startImmediately:使用NO作为最后一个参数。你有效地启动它两次,这可能会导致问题。我建议删除start来电。

  3. 将所有这些设置放在一边,你想要做的是在你的方法中添加一个完成块参数,例如:

    + (void)addPostToServerAddtext:(NSString *)text addimage:(UIImage *)image addbeach:(NSString *)beach location:(NSString*)location completion:(void (^)(id responseObject, NSError *error))completion
    {
        // ...
    
        if (image != nil) {
    
            AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
            [manager POST:[NSString stringWithFormat:@"%@FileUpload",urlBackend] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                [formData appendPartWithFileData:dataImage name:@"image" fileName:ImageName mimeType:@"image/jpg" ];
            } success:^(AFHTTPRequestOperation *operation, id responseObject) {
                if (completion) completion(responseObject, nil);
            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                if (completion) completion(nil, error);
            }];
    
        }
    }
    

    然后你会这样调用:

    [Persistence addPostToServerAddtext:text addimage:image addbeach:nil location:annotation completion:^(id responseObject, NSError *error) {
        if (error) {
            // handle error
            return
        }
    
        // otherwise use the responseObject
    }];
    

    现在,我不知道您要在完成块中返回哪些参数(我假设您想要返回AFHTTPRequestOperationManager所做的内容),但只需更改completion的参数阻止以满足您的需求。

  4. 与您的原始问题无关,但我注意到您正在构建jsonRequest,如下所示:

    NSString *jsonRequest = [NSString stringWithFormat:@"{\"Date\":\"%@\"...."];
    

    如果这些字段中的任何一个包含用户提供的信息(例如,如果用户在所提供的信息中使用双引号,那么这有点风险)。我建议你构建一个字典,然后从中构建jsonRequest。它会更强大。因此:

    NSDictionary *dictionary = @{@"Date"    : date,
                                 @"Message" : message};
    NSError *error = nil;
    NSData *request = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];
    if (error)
        NSLog(@"%s: dataWithJSONObject error: %@", __FUNCTION__, error);
    

    或者,如果您使用AFNetworking,我相信它会为您执行字典的JSON转换。但是,最重要的是,要非常谨慎地自己创建JSON字符串,至少如果请求可能包含任何用户提供的信息。