【发布时间】:2018-04-15 04:17:55
【问题描述】:
我的问题:- NSURLSession 没有释放以前调用的 5MB 块的 API 内存
我在 do while 循环中调用 API 来上传 500MB 视频。我必须使用不同的 API 发送每个 5MB 的块,而不是在一个 API 中。
例如 500MB 视频并创建 100 个块并使用 NSURLSession 发送所以调用 100 次,但 NSURLSession 不会释放先前调用的 5MB 块的 API 内存
(1) 我创建了 5MB 块。
(2) 使用 NSFileHandle 读取 File,使用 OffSet 5MB Chunk
(3) 更改所有块的 URL 并调用 api(需要将所有块发送到不同的 URL)
我不想在 NSData 中转换视频 (500MB) 我想通过 API 发送块
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
//dispatch_group_t group = dispatch_group_create();
__block NSUInteger counterFailure = 0; // PSM Anks calling blob by url fails 4 time, exit for funtion
arrBlobIds = [[NSMutableArray alloc]init];
__block NSInteger intBlockIdCount = 100000; // PSM Anks blobid to assign id to every blob
__block NSUInteger offset = 0; // PSM Anks offset to start posution to read data
NSUInteger length = [[[NSFileManager defaultManager] attributesOfItemAtPath:[urlOfGallaryVideo path] error:nil] fileSize]; // PSM anks total lenght of media
NSUInteger intChunkSize = (5000 * 1024); // PSM anks chunk size
while (offset < length){
//dispatch_group_enter(group);
NSLog(@"offset 1 : %lu",(unsigned long)offset);
// PSM Anks Creat Chunk from file according to length
NSUInteger intThisChunkSize = length - offset > intChunkSize ? intChunkSize : length - offset;
//NSData* chunk = [NSData dataWithBytesNoCopy:(char *)[myBlob bytes] + offset length:intThisChunkSize freeWhenDone:NO];
__block NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:[urlOfGallaryVideo path]];
[fileHandle seekToFileOffset:offset];
__block NSData *dataChunk = [fileHandle readDataOfLength:intThisChunkSize];
// PSM Anks Convert block id in Base 64 encode
NSData *dataBlockId = [[NSString stringWithFormat:@"%ld",intBlockIdCount] dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64BlockId = [dataBlockId base64EncodedStringWithOptions:0];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@&comp=block&blockid=%@",[dictAzureSAS objectForKey:@"uri"],base64BlockId]]];
[request setHTTPMethod:@"PUT"];
[request setHTTPBody:dataChunk];
//[request setValue:[NSString stringWithFormat:@"%lu",(unsigned long)dataChunk.length] forHTTPHeaderField:@"Content-Length"]; // Do not need
//[request setValue:strVideoMIMEType forHTTPHeaderField:@"Content-Type"]; // Do not need
[request addValue:@"BlockBlob" forHTTPHeaderField:@"x-ms-blob-type"];
//NSLog(@"request : %@",request);
//NSLog(@"dataChunk.length : %lu \n url for blob %@ \n request %@",(unsigned long)dataChunk.length,[NSURL URLWithString:[NSString stringWithFormat:@"%@&comp=block&blockid=%@",[dictAzureSAS objectForKey:@"uri"],base64BlockId]],request);
NSLog(@"dataChunk.length : %lu",(unsigned long)dataChunk.length);
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.URLCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
config.timeoutIntervalForRequest = 20.0;
config.URLCredentialStorage = nil;
config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
///NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
config = nil;
//NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *dataTaskForUpload = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"Finished with status code: %li", (long)[(NSHTTPURLResponse *)response statusCode]);
NSLog(@"response: %@", response);
NSLog(@"error: %@ %@", error,error.description);
if(data != nil) // PSM anks Check Data is nil otherwise app crashed
{
NSMutableArray *jsonList = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"jsonList: %@", jsonList);
}
dataChunk = nil;
fileHandle = nil;
if(error == nil)
{
/*
// PSM Anks First Add Then increment
[arrBlobIds addObject:base64BlockId];
intBlockIdCount++;
offset += intThisChunkSize;
counterFailure = 0;
*/
}
else
{
/*
counterFailure++;
offset = intThisChunkSize;
if(counterFailure >= 4)
{
NSLog(@"Enter counter Failure %lu",(unsigned long)counterFailure);
counterFailure = 0;
[self stopLoader];
[CommonAlertViewMsgs cannotConnectServer:self];
return ;
}
*/
}
//dispatch_group_leave(group);
dispatch_semaphore_signal(semaphore);
[session finishTasksAndInvalidate];
}];
[dataTaskForUpload resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"offset 2 : %lu",(unsigned long)offset);
}
【问题讨论】:
-
除了查尔斯在下面的回答,回复
@autoreleasepool,我建议不要为每个请求创建一个新的NSURLSession。 -
@Rob 感谢您的回复,您想说将 500MB 文件拆分为 5MB 文件意味着我想创建 100 个 5MB 文件。然后一个一个上传后
-
@Rob 我建议不要为每个请求创建一个新的 NSURLSession。在 do while loop NSURLSession 中为每个请求创建一个新的,对吗?
-
不,我说的恰恰相反。不要不要在您的
while循环中创建一个新的NSURLSession。在循环之前创建它(也许将它保存在类的某个属性中),然后在循环中简单地使用它。
标签: objective-c nsurlconnection nsurlsession nsurl nsmutableurlrequest