如何从ios正确上传大文件?

时间:2017-05-15 19:55:20

标签: php ios objective-c

我正在尝试从用户设备上传大约50MB但不大于100MB的音频文件到PHP服务器。只要文件很小就没有问题,但是这些较大的文件会导致应用程序因错误而崩溃:“由于内存问题而终止”。是否需要实施像AlamoFire这样的框架来解决这个问题,或者我在文档中遗漏了哪些内容?

谢谢, 这是我的代码:

- (void)initWithWebRequests:(NSMutableURLRequest *)URLRequest inBlock:(ResponseBlock)resBlock 
{
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        __block id responseObjects = nil;

        NSLog(@"URL Request:%@",URLRequest);

        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *task = [session dataTaskWithRequest:URLRequest
                                                completionHandler:
                                      ^(NSData *data, NSURLResponse *response, NSError *error) {
                                          NSString *responseString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
                                          if (data.length > 0)
                                          {
                                              id allValues = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
                                              if([(NSDictionary *)allValues count] <= 0)
                                                  responseString = @"Not Available";
                                              responseObjects = allValues;
                                          }
                                          else if(error != nil)
                                          {
                                              responseString = @"Fail";
                                          }
                                          else if(data.length == 0)
                                          {
                                              responseString = @"Not Available";
                                          }
                                          dispatch_sync(dispatch_get_main_queue(), ^{
                                              [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                                  if (error) {
                                                      resBlock(error, responseObjects, responseString);
                                                  }
                                                  else {
                                                      resBlock(error, responseObjects, responseString);
                                                  }
                                              }];
                                          });
                                      }];

        [task resume];

    });
}];

[operation setQueuePriority:NSOperationQueuePriorityNormal];
[self.operationQueue addOperation:operation];
}

2 个答案:

答案 0 :(得分:1)

使用uploadTaskWithRequest:fromFile:completionHandler:代替dataTaskWithRequest并在fromFile参数中提供请求正文,而不是将其添加到请求中。这可以防止同时将整个文件加载到内存中。

理论上,您可以进行基于流的上传以避免内存影响,但考虑到您所谈论的文件大小,我假设您最终想要考虑使用后台NSURLSession。对于后台上传请求,您确实希望使用基于文件的上传,而不是基于流的方法。

在回答您的框架问题时,像Alamofire这样的库(或者,更合适的是,您使用的是Objective-C,AFNetworking,来自同一作者的Objective-C网络库)有助于创建复杂的请求,所以你可能会考虑这一点,但它与你在这里的内存问题无关。

答案 1 :(得分:0)

尝试此AFNetworking代码导入#import“AFHTTPSessionManager.h”此文件

[SVProgressHUD showWithStatus:@"Loading..."];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:URL parameters:postParams constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
     [formData appendPartWithFileData:imageData name:@"Key" fileName:@"image" mimeType:@"image/jpeg"];
} error:nil];


AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

NSURLSessionUploadTask *uploadTask;

uploadTask = [manager
              uploadTaskWithStreamedRequest:request
              progress:^(NSProgress * _Nonnull uploadProgress)
              {
                  NSLog(@"%@",uploadProgress);
              }
              completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error)
              {
                  if (error)
                  {
                      [SVProgressHUD dismiss];

                  }
                  else
                  {
                      [SVProgressHUD dismiss];

                  }
              }];
[uploadTask resume];