https://github.com/agelessman/MCDownloader
第一个是多个任务同时加载导致部分资源超时的问题
主要是_downloadQueue.maxConcurrentOperationCount = 3;
还有
_downloadTimeout = 30.0;
sessionConfiguration.timeoutIntervalForRequest = _downloadTimeout;
sessionConfiguration.HTTPMaximumConnectionsPerHost = 50;
第一处控制并发量
第二三处控制不超时
- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration {
if ((self = [super init])) {
_operationClass = [MCDownloadOperation class];
_downloadPrioritizaton = MCDownloadPrioritizationFIFO;
_downloadQueue = [NSOperationQueue new];
_downloadQueue.maxConcurrentOperationCount = 3;
_downloadQueue.name = @"com.machao.MCDownloader";
_URLOperations = [NSMutableDictionary new];
_barrierQueue = dispatch_queue_create("com.machao.MCDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT);
_downloadTimeout = 30.0;
sessionConfiguration.timeoutIntervalForRequest = _downloadTimeout;
sessionConfiguration.HTTPMaximumConnectionsPerHost = 50;
/**
* Create the session for this task
* We send nil as delegate queue so that the session creates a serial operation queue for performing all delegate
* method calls and completion handler calls.
*/
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
return self;
}
第二个是出现下载的数据丢失的情况(主要是一开始的数据)
没有实现对应各个block导致头部数据丢失,从而导致下载的zip包数据不完整无法解压
MCDownloadOperation.m
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
__block NSError *error = nil;
MCDownloadReceipt *receipt = [[MCDownloader sharedDownloader] downloadReceiptForURLString:self.request.URL.absoluteString];
// Speed
receipt.totalRead += data.length;
NSDate *currentDate = [NSDate date];
if ([currentDate timeIntervalSinceDate:receipt.date] >= 1) {
double time = [currentDate timeIntervalSinceDate:receipt.date];
long long speed = receipt.totalRead/time;
receipt.speed = [self formatByteCount:speed];
receipt.totalRead = 0.0;
receipt.date = currentDate;
}
// Write Data
NSInputStream *inputStream = [[NSInputStream alloc] initWithData:data];
NSOutputStream *outputStream = [[NSOutputStream alloc] initWithURL:[NSURL fileURLWithPath:receipt.filePath] append:YES];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
while ([inputStream hasBytesAvailable] && [outputStream hasSpaceAvailable]) {
uint8_t buffer[1024];
NSInteger bytesRead = [inputStream read:buffer maxLength:1024];
if (inputStream.streamError || bytesRead < 0) {
error = inputStream.streamError;
break;
}
NSInteger bytesWritten = [outputStream write:buffer maxLength:(NSUInteger)bytesRead];
if (outputStream.streamError || bytesWritten < 0) {
error = outputStream.streamError;
break;
}
if (bytesRead == 0 && bytesWritten == 0) {
break;
}
}
[outputStream close];
[inputStream close];
receipt.progress.totalUnitCount = receipt.totalBytesExpectedToWrite;
receipt.progress.completedUnitCount = receipt.totalBytesWritten;
dispatch_main_async_safe(^{
for (MCDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) {
progressBlock(receipt.progress.completedUnitCount, receipt.progress.totalUnitCount, receipt.speed.integerValue, self.request.URL);
}
if (self.receipt.downloaderProgressBlock) {
self.receipt.downloaderProgressBlock(receipt.progress.completedUnitCount, receipt.progress.totalUnitCount, receipt.speed.integerValue, self.request.URL);
}
});
}