4

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)));
    }];
S.J
  • 3,063
  • 3
  • 33
  • 66

3 Answers3

2
@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
Guy Kogus
  • 7,251
  • 1
  • 27
  • 32
  • Thanks a lot ... its working perfectly. What I was trying to do for getting a firm grip on memory management is that I read al the image gallery url through alasset library and stored in my array, now I want to upload all images, as the loop starts app crashes reading around 10 images because I have 100+ images of size 6 mb. To solve this issue I removed the for loop and made a recursive approach, Read one image at a time upload it and in its success block call the same method for more images upload. But now i want to upload a single large file like 200mb+, what will be the correct approach. – S.J Dec 20 '12 at 07:08
  • Uploading a 200MB+ file? That's beyond me. My guess would be to create an NSData instance using `initWithContentsOfFile:options:error:` with the NSDataReadingMappedAlways option, then send that into the upload request. I've never tried anything like this, so play with it and have fun :) If you're really stuck I recommend opening a new question on StackOverflow, since this question's marked as answered. – Guy Kogus Dec 24 '12 at 12:12
0

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

amb
  • 4,798
  • 6
  • 41
  • 68
0

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]
Guy Kogus
  • 7,251
  • 1
  • 27
  • 32
  • thanks for reply ... i tried autoreleasepool still its crashing but duration increased and please can you give me a detail snippet how to use [httpClient enqueueHTTPRequestOperation:operation]. – S.J Dec 18 '12 at 13:07