Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending more than one image with AFNetworking

I'm developing a messaging app, and users can also send pictures to one another.
When a user sends more than one picture I send them in parallel (I don't wait for the first one to finish upload before I send the second one)

Before moving to AFNetworking I succeeded in doing this with ASIFormDataRequest, and indeed if I sent 2 images, both of them were transmitted in parallel and successfully delivered to the other user.

When I try doing this with AFNetworking, I get some strange behavior.
I'll try to describe the case were user1 send two images too user2:

  1. User1 send image1 -> everything looks ok, I can see the upload progress.
  2. User1 then send image2 -> still looks ok, I can see the upload progress of both images
  3. image1 upload is finished -> user2 gets a corrupted image that looks like a combination of image1 and image2 together!
  4. image2 upload is finished -> user2 gets image2 successfully

This is how I send an image

- (void)sendImageMsgWithPath:(NSString *)path
                       image:(UIImage *)image
                     success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                     failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
                    progress:(void (^)(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress
{
    NSData *imageData = UIImageJPEGRepresentation(image, 0.5);

    // create the request

    NSURLRequest *request = [[AppClient sharedClient] multipartFormRequestWithMethod:@"POST" path:path parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) 
                             {
                                 [formData appendPartWithFileData:imageData name:@"image_name" fileName:@"image_name.jpg" mimeType:@"image/jpeg"];
                             }];


    // create the operation

    AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];

    // set progress block

    [operation setUploadProgressBlock:progress];

    //set completion blocks

    [operation setCompletionBlockWithSuccess:success failure:failure];

    // set it to work in background

    [operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:nil];

    // add it to the operations queue

    [[AppClient sharedClient] enqueueHTTPRequestOperation:operation];
}

*** the path for both image uploads is the same:

path = @"FrontEnd?cmd=sendimage&fromuserid=3&touserid=1&"

it will be added to the baseURL to create the coplete URL:

@"http://somename.myftp.org:8080/web_proj/FrontEnd?cmd=sendimage&fromuserid=3&touserid=1"

This are the images I sent:
image1
enter image description here

image2
enter image description here

corrupted image
enter image description here

like image 874
Eyal Avatar asked Jul 11 '12 12:07

Eyal


2 Answers

Use a multipartFormRequest for that use below method:

- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
                                               path:(NSString *)path
                                         parameters:(NSDictionary *)parameters
                          constructingBodyWithBlock:(void (^)(id <AFMultipartFormDataProxy>formData))block;

For example like this:

 NSURLRequest* request = [[YourHTTPClient sharedHTTPClient] multipartFormRequestWithMethod:@"POST"
                     path:path
                     parameters:dict
                     constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                          [formData appendPartWithFileData:data1
                                                      name:@"image1"
                                                      fileName:@"image1.jpg"
                                                      mimeType:@"image/jpeg"];
                          [formData appendPartWithFileData:data2
                                                      name:@"image2"
                                                      fileName:@"image2.jpg"
                                                      mimeType:@"image/jpeg"];
                     }
                 }];
like image 138
Paresh Navadiya Avatar answered Oct 18 '22 09:10

Paresh Navadiya


How are you creating the UIImage objects that get passed into your sendImageMsgWithPath: method? Are you creating them using imageWithData: (or similar)? If so, I have seen problems like this when trying to reuse an NSMutableData. It seems that even after you create the UIImage, the subsystem still needs to read that data at a later time. And if you have since reused that NSMutableData, the image will be corrupted.

If this is the case, I recommend that you use a new NSMutableData to create each UIImage.

like image 33
Nate Petersen Avatar answered Oct 18 '22 10:10

Nate Petersen