【问题标题】:Need assistance uploading multiple large image from ios device需要帮助从 ios 设备上传多个大图像
【发布时间】:2012-12-18 11:33:28
【问题描述】:

我使用 alasset 库成功获取了我的 iphone 图片库中的所有图片 url 并存储在一个数组中。现在我正在尝试上传到服务器,这是我的代码:

我尝试了两种方法,但都在迭代大约 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)));
    }];

【问题讨论】:

    标签: ios nsurlconnection afnetworking nsinputstream


    【解决方案1】:
    @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
    

    【讨论】:

    • 非常感谢......它工作得很好。为了牢牢掌握内存管理,我试图做的是我通过 alasset 库读取所有图片库 url 并存储在我的数组中,现在我想上传所有图片,因为循环开始应用程序崩溃,读取大约 10 张图片因为我有 100 多张 6 mb 的图片。为了解决这个问题,我删除了 for 循环并采用递归方法,一次读取一个图像上传它,并在其成功块中调用相同的方法来上传更多图像。但是现在我想上传一个像 200mb+ 这样的大文件,正确的方法是什么。
    • 上传 200MB 以上的文件?这超出了我的范围。我的猜测是使用带有 NSDataReadingMappedAlways 选项的initWithContentsOfFile:options:error: 创建一个 NSData 实例,然后将其发送到上传请求中。我从来没有尝试过这样的事情,所以玩它并玩得开心:) 如果你真的被卡住了,我建议在 StackOverflow 上打开一个新问题,因为这个问题被标记为已回答。
    【解决方案2】:

    你应该在设置完成和进度块回调后[operation start];

    【讨论】:

      【解决方案3】:

      您的崩溃可能是由于内存过载。首先,在第 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]
      

      【讨论】:

      • 感谢回复...我尝试了 autoreleasepool 仍然崩溃,但持续时间增加了,请您给我详细说明 sn-p 如何使用 [httpClient enqueueHTTPRequestOperation:operation]。
      猜你喜欢
      • 1970-01-01
      • 2012-05-13
      • 1970-01-01
      • 2013-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      相关资源
      最近更新 更多