Нужна помощь в загрузке нескольких больших изображений с устройства ios

Я успешно получил все URL-адреса изображений в моей галерее изображений iphone, используя библиотеку alasset, и сохранил их в массиве. Теперь я пытаюсь загрузить на сервер, вот мой код:

Я пробовал два подхода, но оба вылетали после повторения около 10 изображений без какого-либо журнала сбоев. Изображения не загружаются на сервер, перед загрузкой происходит сбой.

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. Использование межсетевого взаимодействия

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)));
    }];

person S.J    schedule 18.12.2012    source источник


Ответы (3)


Вы должны [operation start]; после установки обратных вызовов блоков завершения и прогресса.

person amb    schedule 18.12.2012

Ваши сбои потенциально связаны с перегрузкой памяти. Во-первых, в разделе 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++)
    {
        @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]);
                                   }];
        }
    }

Такие методы, как imageWithCGImage: и UIImageJPEGRepresentation, возвращают большие автоматически освобождаемые объекты, поэтому вам необходимо обеспечить их освобождение как можно скорее, чтобы освободить память.

В разделе 2:

Что касается AFNetworking, звонить [operation start] бесполезно. Операция будет выпущена, как только она выйдет за рамки, поэтому вряд ли она действительно завершится. Вам нужно сохранить экземпляр AFHTTPClient (обычно он делается как синглтон, но свойство достаточно хорошо) и поставить в очередь операции с ним, вызвав:

[httpClient enqueueHTTPRequestOperation:operation]
person Guy Kogus    schedule 18.12.2012
comment
спасибо за ответ ... я попробовал autoreleasepool, но он все еще дает сбой, но продолжительность увеличилась, и, пожалуйста, не могли бы вы дать мне подробный фрагмент, как использовать [httpClient enqueueHTTPRequestOperation:operation]. - person S.J; 18.12.2012

person    schedule
comment
Большое спасибо... работает отлично. То, что я пытался сделать, чтобы получить твердый контроль над управлением памятью, заключается в том, что я прочитал все URL-адрес галереи изображений через библиотеку alasset и сохранил в своем массиве, теперь я хочу загрузить все изображения, так как цикл запускает приложение сбой, читая около 10 изображений потому что у меня есть 100+ изображений размером 6 мб. Чтобы решить эту проблему, я удалил цикл for и применил рекурсивный подход: прочитайте одно изображение за раз, загрузите его и в блоке успеха вызовите тот же метод для загрузки большего количества изображений. Но теперь я хочу загрузить один большой файл, например, 200 МБ+, что будет правильным подходом. - person S.J; 20.12.2012
comment
Загружаете файл размером более 200 МБ? Это вне меня. Я предполагаю, что нужно создать экземпляр NSData, используя initWithContentsOfFile:options:error: с параметром NSDataReadingMappedAlways, а затем отправить его в запрос на загрузку. Я никогда не пробовал ничего подобного, так что играйте и получайте удовольствие :) Если вы действительно застряли, я рекомендую открыть новый вопрос на StackOverflow, так как этот вопрос помечен как ответ. - person Guy Kogus; 24.12.2012