Question

I successfully fetched all images url in my iphone image gallery using alasset library and stored in an array. Now i am trying to upload to server, here is my code:

I tried two approaches, but both crashes after iterating around 10 images, with out any crash log. Images do not upload to server, it crashes before uploading.

1:

NSData *imgData; UIImage *img; NSInputStream *stream;

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://my.url.com"]];

for(int i=0; i<_dataContainer.count; i++)
{
    img = [UIImage imageWithCGImage:[[[_dataContainer objectAtIndex:i] defaultRepresentation]fullResolutionImage]];
    imgData = UIImageJPEGRepresentation(img, 1.0);
    stream = [[NSInputStream alloc] initWithData:imgData];
    [request setHTTPBodyStream:stream];
    [request setHTTPMethod:@"POST"];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                               NSLog(@"Finished with status code: %i", [(NSHTTPURLResponse *)response statusCode]);
                           }];
}

2: Using Afnetworking

AFHTTPClient *client= [[AFHTTPClient alloc]initWithBaseURL:[NSURL URLWithString:@"http://my.url.com"]];
     NSURLRequest *myRequest;
    __block UIImage *img;
    __block NSData *imgData;
    __block NSString *fName;


    myRequest = [client multipartFormRequestWithMethod:@"POST" path:@"/images/mypage.php" parameters:nil constructingBodyWithBlock:
                 ^(id <AFMultipartFormData>formData)
                 {                     
                     img = [UIImage imageWithCGImage:[[[_dataContainer objectAtIndex:0] defaultRepresentation]fullResolutionImage]];
                     imgData = UIImageJPEGRepresentation(img, 1.0);
                     fName = [self returnDateTimeWithMilliSeconds];

                     [formData appendPartWithFileData:imgData name:@"photo" fileName:[NSString stringWithFormat:@"%@.jpg",fName] mimeType:@"image/jpeg"];

                     NSLog(@"FN=>%@ | Size=>%@",fName, [NSByteCountFormatter stringFromByteCount:[imgData length] countStyle:NSByteCountFormatterCountStyleFile]);
                 }];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:myRequest];
    [operation start];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
     {

         NSLog(@"Success Data -> %@", operation.responseString);
     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
         NSLog(@"Failed");
     }];

    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
        NSLog(@"Progrees -> %f", ((float)((int)totalBytesWritten) / (float)((int)totalBytesExpectedToWrite)));
    }];
Was it helpful?

Solution

@interface MyHTTPClient : AFHTTPClient

+ (id)sharedClient;

@end

@implementation MyHTTPClient

+ (id)sharedClient
{
    static MyHTTPClient *sharedClient;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedClient = [[MyHTTPClient alloc] initWithBaseURL:nil];
    });
    return sharedClient;
}

@end

@implementation MyViewController

- (void)uploadImages
{
    NSURLRequest *myRequest;
    __block UIImage *img;
    __block NSData *imgData;
    __block NSString *fName;


    myRequest = [client multipartFormRequestWithMethod:@"POST" path:@"/images/mypage.php" parameters:nil constructingBodyWithBlock:
                 ^(id <AFMultipartFormData>formData)
                 {                     
                     img = [UIImage imageWithCGImage:[[[_dataContainer objectAtIndex:0] defaultRepresentation]fullResolutionImage]];
                     imgData = UIImageJPEGRepresentation(img, 1.0);
                     fName = [self returnDateTimeWithMilliSeconds];

                     [formData appendPartWithFileData:imgData name:@"photo" fileName:[NSString stringWithFormat:@"%@.jpg",fName] mimeType:@"image/jpeg"];

                     NSLog(@"FN=>%@ | Size=>%@",fName, [NSByteCountFormatter stringFromByteCount:[imgData length] countStyle:NSByteCountFormatterCountStyleFile]);
                 }];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:myRequest];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
     {

         NSLog(@"Success Data -> %@", operation.responseString);
     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
         NSLog(@"Failed");
     }];

    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
        NSLog(@"Progrees -> %f", ((float)((int)totalBytesWritten) / (float)((int)totalBytesExpectedToWrite)));
    }];

    [[MyHTTPClient sharedClient] enqueueHTTPRequestOperation:operation]
}

@end

OTHER TIPS

You should [operation start]; after setting the completion and progress block callbacks.

Your crashes are potentially due to overloading the memory. Firstly, in section 1, you need to drain the autorelease pool on each iteration, as such:

NSData *imgData; UIImage *img; NSInputStream *stream;

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://my.url.com"]];

    for(int i=0; i<_dataContainer.count; i++)
    {
        @autoreleasepool {
            img = [UIImage imageWithCGImage:[[[_dataContainer objectAtIndex:i] defaultRepresentation]fullResolutionImage]];
            imgData = UIImageJPEGRepresentation(img, 1.0);
            stream = [[NSInputStream alloc] initWithData:imgData];
            [request setHTTPBodyStream:stream];
            [request setHTTPMethod:@"POST"];
            [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
                                   completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                                       NSLog(@"Finished with status code: %i", [(NSHTTPURLResponse *)response statusCode]);
                                   }];
        }
    }

Methods like imageWithCGImage: and UIImageJPEGRepresentation return large autoreleased objects, so you need to ensure that they're released ASAP to free up memory.

In section 2:

In regards to AFNetworking, calling [operation start] is useless. The operation will be released as soon as it's out of scope, so it's unlikely to actually complete. You need to retain the AFHTTPClient instance (usually done as a singleton, but a property is good enough) and enqueue operations on it by calling:

[httpClient enqueueHTTPRequestOperation:operation]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top