您的位置:首页 > 移动开发 > IOS开发

iOS文件上传遇到的坑

2016-06-19 23:25 549 查看

背景

在我们的app中有一些需要做文件上传的功能,最近在我们对文件上传结果的日志监控中收到了很多的超时信息,后来在实际文件上传的测试中发现一些问题,主要集中在大批文件上传上面,简单分享一下。

问题

在批量文件上传中,通过测试发现,使用NSURLSessionUploadTask的形式进行文件上传,如果同时启动过多的上传任务,会导致上传任务的失败率极高,失败的原因基本都是请求超时。

按照以下方式对文件上传进行测试。

- (void)beginUpload {
NSMutableArray *uploadTasks = [NSMutableArray array];
NSString *path = [[NSBundle mainBundle] pathForResource:@"abc" ofType:@"jpg"];
NSData *data = [NSData dataWithContentsOfFile:path];
for (NSInteger i = 0; i < 1000; i++) {
NSString *key = [NSString stringWithFormat:@"%zd.jpeg", i];
NSString *url = [NSString stringWithFormat:@"http://upload.server.com?a=%zd", i];
[uploadTasks addObject:[self uploadData:data key:key url:url]];
}
}

- (NSURLSessionUploadTask *)uploadData:(NSData *)data key:(NSString *)key url:(NSString *)url{
NSDictionary *params = @{@"key": key,
@"token": @"1231321231"};
NSMutableURLRequest *request = [self.httpManager.requestSerializer
multipartFormRequestWithMethod:@"POST"
URLString:url
parameters:params
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:data name:@"file" fileName:key mimeType:@"application/octet-stream"];
}

error:nil];
request.timeoutInterval = 10;
NSURLSessionUploadTask *uploadTask = [self.httpManager uploadTaskWithRequest:request fromData:nil progress:nil completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
if (error == nil) {
NSLog(@"文件上传成功");
} else {
NSLog(@"文件上传失败 -> %@", error.userInfo[@"NSErrorFailingURLStringKey"]);
}
}];
[uploadTask resume];
return uploadTask;
}


测试结果为:

同样的超时时长、同样的网速状态下,同时启动的上传任务只有前面几个会成功,后面的任务会超时。

其中,当前两个条件没有变化时,任务数量达到一定数量后后面的基本就都会失败。

例如:设置超时10s,在上传速度1M/s的网络状态下,上传800k的文件,同时启动n>50个上传任务,能成功上传的稳定在18个左右)

解决方案

控制同时启动的上传任务数量,既不能过少,也不能过多,在有任务结束时再启动新的上传任务。

这样既能充分利用网络资源,又不会导致过多的任务同时启动造成超时。

其它

文件上传中另外一个注意点是对于大文件的上传,不能把文件直接读入内存去上传,你可以使用NSFileHandle来分片读取大文件完成上传。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 文件上传