简体   繁体   English

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

[英]How to properly upload large files from ios?

I am attempting to upload audio files, around 50MB but no larger than 100MB, from the users device to a PHP server. 我正在尝试从用户设备向PHP服务器上载大约50MB但不大于100MB的音频文件。 As long as the files are small there's no issue, but these larger files cause the app to crash due to the error: "Terminated due to memory issue". 只要文件很小,就没有问题,但是这些较大的文件会由于以下错误而导致应用程序崩溃:“由于内存问题而终止”。 Would implementation of a framework such as AlamoFire be necessary to solve this issue or is there something I missed in the documentation? 解决该问题是否需要实施AlamoFire之类的框架,或者我在文档中缺少某些内容?

Thanks, Here is my code: 谢谢,这是我的代码:

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

Use uploadTaskWithRequest:fromFile:completionHandler: instead of dataTaskWithRequest and supply the body of the request in the fromFile parameter rather than adding it to the request. 使用uploadTaskWithRequest:fromFile:completionHandler:代替dataTaskWithRequest并在fromFile参数中提供请求的正文,而不是将其添加到请求中。 That prevents loading the whole file into memory at the same time. 这样可以防止将整个文件同时加载到内存中。

Theoretically, you could do a streaming-based upload to avoid the memory impact, too, but given the file sizes that you're talking about, I assume you eventually want to considering using background NSURLSession . 从理论上讲,您也可以进行基于流的上载以避免对内存的影响,但是考虑到要讨论的文件大小,我认为您最终想考虑使用背景NSURLSession And for background upload requests, you really want to use file-based uploads, not streaming-based approaches. 对于后台上传请求,您确实要使用基于文件的上传,而不是基于流的方法。

In answer to your framework question, libraries like Alamofire (or, more appropriate given that you're using Objective-C, AFNetworking , an Objective-C networking library from the same author) help create complicated requests, so you might consider that, but it has nothing to do with the memory issue you have here. 为了回答您的框架问题,像Alamofire之类的库(或者,如果您使用的是Objective-C, AFNetworking (来自同一作者的Objective-C网络库,更合适),则可以帮助创建复杂的请求,因此您可以考虑一下,但是它与您在此处遇到的内存问题无关。

Try this AFNetworking code import #import "AFHTTPSessionManager.h" this file 试试这个AFNetworking代码import #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];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM