Имате нужда от помощ при качване на няколко големи изображения от 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: Използване на 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)));
    }];

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 mb. За да реша този проблем, премахнах цикъла for и направих рекурсивен подход, четете едно изображение наведнъж, качвайте го и в неговия блок за успех извиквайте същия метод за качване на повече изображения. Но сега искам да кача един голям файл като 200mb+, какъв ще бъде правилният подход. - person S.J; 20.12.2012
comment
Качвате 200MB+ файл? Това е извън мен. Моето предположение би било да създадете екземпляр на NSData, използвайки initWithContentsOfFile:options:error: с опцията NSDataReadingMappedAlways, след което да го изпратите в заявката за качване. Никога не съм опитвал нещо подобно, така че играйте с него и се забавлявайте :) Ако наистина сте блокирани, препоръчвам ви да отворите нов въпрос в StackOverflow, тъй като този въпрос е маркиран като отговорен. - person Guy Kogus; 24.12.2012