Ios 有多个文件下载问题
目前我正在实现一个文件下载应用程序。 在我的应用服务器中有大约2500个资源文件,我需要将这些文件从服务器下载到我的文档目录中 我的代码:Ios 有多个文件下载问题,ios,nsurlsession,nsurlsessiondownloadtask,nsurlsessionconfiguration,Ios,Nsurlsession,Nsurlsessiondownloadtask,Nsurlsessionconfiguration,目前我正在实现一个文件下载应用程序。 在我的应用服务器中有大约2500个资源文件,我需要将这些文件从服务器下载到我的文档目录中 我的代码: @implementation DownloadManager { NSURLSession *session; BOOL downloading; } #pragma mark - NSURLSessionDownloadDelegate // Handle download completion from the task - (vo
@implementation DownloadManager
{
NSURLSession *session;
BOOL downloading;
}
#pragma mark - NSURLSessionDownloadDelegate
// Handle download completion from the task
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSInteger index = [self assetDownloadIndexForDownloadTask:downloadTask];
if (index < 0)
{
return;
}
DownloadHelper *movieDownload = _assetsToDownload[index];
// Copy temporary file
NSError * error;
[[NSFileManager defaultManager] copyItemAtURL:location toURL:[NSURL fileURLWithPath:[movieDownload localPath]] error:&error];
downloading = NO;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
// Required delegate method
}
// Handle task completion
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error)
NSLog(@"Task %@ failed: %@", task, error);
NSLog(@"Task %@ Success: %@", task, error);
if ([_assetsToDownload count])
{
[_assetsToDownload removeObjectAtIndex:0];
}
downloading = NO;
if ([_assetsToDownload count])
{
[self downloadFiles];
}
else
{
[self downloadAssets];
}
}
// Handle progress update from the task
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSInteger index = [self assetDownloadIndexForDownloadTask:downloadTask];
if (index < 0) return;
// DownloadHelper *movieDownload = _assetsToDownload[index];
double progress = (double) (totalBytesWritten/1024) / (double) (totalBytesExpectedToWrite/1024);
dispatch_async(dispatch_get_main_queue(), ^{
// Showing progress
});
}
#pragma mark - Movie Download Handling & UI
// Helper method to get the index of a Asset from the array based on downloadTask.
- (NSInteger)assetDownloadIndexForDownloadTask:(NSURLSessionDownloadTask *)downloadTask
{
NSInteger foundIndex = -1;
NSInteger index = 0;
for (DownloadHelper *asset in _assetsToDownload)
{
if (asset.downloadTask == downloadTask)
{
foundIndex = index;
break;
}
index++;
}
return foundIndex;
}
- (void)addAssetDownload
{
DownloadInfo *info = nil;
NSString *assetFolder = nil;
for (int index = 0; index<[_assets count]; index++)
{
info = [_assets objectAtIndex:index];
NSURL *url = [NSURL URLWithString:info.assetURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
DownloadHelper *assetDownload = [[DownloadHelper alloc] initWithURL:url downloadTask:downloadTask];
assetDownload.assetName = info.assetName;
if (info.categoryId == 1)
{
assetFolder = [self getImagePath:info.assetName];
}
else if (info.categoryId == 2)
{
assetFolder = [self getVideoPath:info.assetName];
}
else if (info.categoryId == 3)
{
//assetFolder = [self getDBPath:info.assetName];
}
else
{
assetFolder = [self filePath:info.assetName];
}
assetDownload.assetFolder = assetFolder;
[_assetsToDownload addObject:assetDownload];
}
}
// Initialize the download, session and tasks
- (void)initialize
{
for (DTEDownloadHelper *movieDownload in _assetsToDownload)
{
// Cancel each task
NSURLSessionDownloadTask *downloadTask = movieDownload.downloadTask;
[downloadTask cancel];
}
// Cancel all tasks and invalidate the session (also releasing the delegate)
[session invalidateAndCancel];
session = nil;
_assetsToDownload = [[NSMutableArray alloc] init];
// Create a session configuration passing in the session ID
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"DTEDownloadBackground"];
sessionConfiguration.discretionary = YES;
session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
[self addAssetDownload];
// Reset the UI
downloading = NO;
[self downloadFiles];
}
// Download handler
- (void)downloadFiles
{
if ([_assetsToDownload count] > 0)
{
// Acquire the appropriate downloadTask and respond appropriately to the user's selection
NSURLSessionDownloadTask * downloadTask = [_assetsToDownload[0] downloadTask];
if (downloadTask.state == NSURLSessionTaskStateCompleted)
{
// Download is complete. Play movie.
// NSURL *movieURL = [NSURL fileURLWithPath:[_assetsToDownload[0] localPath]];
}
else if (downloadTask.state == NSURLSessionTaskStateSuspended)
{
// If suspended and not already downloading, resume transfer.
if (!downloading)
{
[self showHUD:[NSString stringWithFormat:@"Downloading %@",[_assetsToDownload[0] assetName]]];
[downloadTask resume];
downloading = YES;
}
}
else if (downloadTask.state == NSURLSessionTaskStateRunning)
{
// If already downloading, pause the transfer.
[downloadTask suspend];
downloading = NO;
}
}
}
- (void)downloadAssets
{
_assets = [self retreiveAssets]; // Getting the resource details from the database
if (![_assets count])
{
// Hide progress
}
[self addAssetDownload];
[self downloadFiles];
}
@end
@实现下载管理器
{
NSURL会议*会议;
BOOL下载;
}
#pragma标记-NSURLSessionDownloadDelegate
//处理任务中的下载完成
-(void)URLSession:(NSURLSession*)会话下载任务:(NSURLSessionDownloadTask*)下载任务未完成下载教程:(NSURL*)位置
{
NSInteger索引=[self-assetDownloadIndexForDownloadTask:downloadTask];
如果(指数<0)
{
返回;
}
DownloadHelper*movieDownload=_assetsToDownload[index];
//复制临时文件
n错误*错误;
[[NSFileManager defaultManager]CopyItemAttribute:location Tour:[NSURL fileURLWithPath:[movieDownload localPath]]错误:&错误];
下载=否;
}
-(void)URLSession:(NSURLSession*)会话下载任务:(NSURLSessionDownloadTask*)下载任务DidResumeAtoOffset:(int64_t)文件偏移量预期总字节数:(int64_t)预期总字节数
{
//必需的委托方法
}
//处理任务完成
-(void)URLSession:(NSURLSession*)会话任务:(NSURLSessionTask*)任务未完成错误:(NSError*)错误
{
如果(错误)
NSLog(@“任务%@失败:%@”,任务,错误);
NSLog(@“任务%@成功:%@”,任务,错误);
如果([\u assetsToDownload count])
{
[\u assetsToDownload removeObjectAtIndex:0];
}
下载=否;
如果([\u assetsToDownload count])
{
[自动下载文件];
}
其他的
{
[自下载资产];
}
}
//处理来自任务的进度更新
-(void)URLSession:(NSURLSession*)会话下载任务:(NSURLSessionDownloadTask*)下载任务didWriteData:(int64_t)BytesWritedTotalBytesWrited:(int64_t)TotalBytesWritedTotalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSInteger索引=[self-assetDownloadIndexForDownloadTask:downloadTask];
如果(指数<0)返回;
//DownloadHelper*movieDownload=_assetsToDownload[index];
double progress=(double)(totalBytesWrite/1024)/(double)(totalBytesExpectedToWrite/1024);
dispatch\u async(dispatch\u get\u main\u queue()^{
//显示进步
});
}
#pragma标记-电影下载处理和用户界面
//基于downloadTask从数组中获取资源索引的助手方法。
-(NSInteger)assetDownloadIndexForDownloadTask:(NSURLSessionDownloadTask*)downloadTask
{
NSInteger foundIndex=-1;
NSInteger指数=0;
对于(下载助手*资产在_assetsToDownload中)
{
if(asset.downloadTask==downloadTask)
{
foundIndex=索引;
打破
}
索引++;
}
收益率指数;
}
-(无效)添加组件下载
{
DownloadInfo*info=nil;
NSString*assetFolder=nil;
对于(int索引=0;索引0)
{
//获取适当的下载任务,并对用户的选择做出适当的响应
NSURLSessionDownloadTask*downloadTask=[[U assetsToDownload[0]downloadTask];
if(downloadTask.state==NSURLSessionTaskStateCompleted)
{
//下载完成。播放电影。
//NSURL*movieURL=[NSURL fileURLWithPath:[[U assetsToDownload[0]localPath]];
}
else if(downloadTask.state==nsurlsessiontaskstatesupspended)
{
//如果已挂起且尚未下载,请恢复传输。
如果(!正在下载)
{
[self showHUD:[NSString stringWithFormat:@“Downloading%@,[[u assetsToDownload[0]assetName]];
[下载任务恢复];
下载=是;
}
}
else if(downloadTask.state==NSURLSessionTaskStateRunning)
{
//如果已下载,请暂停传输。
[下载任务暂停];
下载=否;
}
}
}
-(作废)下载资产
{
_assets=[self-retreiveAssets];//从数据库获取资源详细信息
如果(![\u资产计数])
{
//隐藏进度
}
[自添加组件下载];
[自动下载文件];
}
@结束
问题:
@implementation DownloadManager
{
NSURLSession *session;
BOOL downloading;
}
#pragma mark - NSURLSessionDownloadDelegate
// Handle download completion from the task
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSInteger index = [self assetDownloadIndexForDownloadTask:downloadTask];
if (index < 0)
{
return;
}
DownloadHelper *movieDownload = _assetsToDownload[index];
// Copy temporary file
NSError * error;
[[NSFileManager defaultManager] copyItemAtURL:location toURL:[NSURL fileURLWithPath:[movieDownload localPath]] error:&error];
downloading = NO;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
// Required delegate method
}
// Handle task completion
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error)
NSLog(@"Task %@ failed: %@", task, error);
NSLog(@"Task %@ Success: %@", task, error);
if ([_assetsToDownload count])
{
[_assetsToDownload removeObjectAtIndex:0];
}
downloading = NO;
if ([_assetsToDownload count])
{
[self downloadFiles];
}
else
{
[self downloadAssets];
}
}
// Handle progress update from the task
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSInteger index = [self assetDownloadIndexForDownloadTask:downloadTask];
if (index < 0) return;
// DownloadHelper *movieDownload = _assetsToDownload[index];
double progress = (double) (totalBytesWritten/1024) / (double) (totalBytesExpectedToWrite/1024);
dispatch_async(dispatch_get_main_queue(), ^{
// Showing progress
});
}
#pragma mark - Movie Download Handling & UI
// Helper method to get the index of a Asset from the array based on downloadTask.
- (NSInteger)assetDownloadIndexForDownloadTask:(NSURLSessionDownloadTask *)downloadTask
{
NSInteger foundIndex = -1;
NSInteger index = 0;
for (DownloadHelper *asset in _assetsToDownload)
{
if (asset.downloadTask == downloadTask)
{
foundIndex = index;
break;
}
index++;
}
return foundIndex;
}
- (void)addAssetDownload
{
DownloadInfo *info = nil;
NSString *assetFolder = nil;
for (int index = 0; index<[_assets count]; index++)
{
info = [_assets objectAtIndex:index];
NSURL *url = [NSURL URLWithString:info.assetURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
DownloadHelper *assetDownload = [[DownloadHelper alloc] initWithURL:url downloadTask:downloadTask];
assetDownload.assetName = info.assetName;
if (info.categoryId == 1)
{
assetFolder = [self getImagePath:info.assetName];
}
else if (info.categoryId == 2)
{
assetFolder = [self getVideoPath:info.assetName];
}
else if (info.categoryId == 3)
{
//assetFolder = [self getDBPath:info.assetName];
}
else
{
assetFolder = [self filePath:info.assetName];
}
assetDownload.assetFolder = assetFolder;
[_assetsToDownload addObject:assetDownload];
}
}
// Initialize the download, session and tasks
- (void)initialize
{
for (DTEDownloadHelper *movieDownload in _assetsToDownload)
{
// Cancel each task
NSURLSessionDownloadTask *downloadTask = movieDownload.downloadTask;
[downloadTask cancel];
}
// Cancel all tasks and invalidate the session (also releasing the delegate)
[session invalidateAndCancel];
session = nil;
_assetsToDownload = [[NSMutableArray alloc] init];
// Create a session configuration passing in the session ID
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"DTEDownloadBackground"];
sessionConfiguration.discretionary = YES;
session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
[self addAssetDownload];
// Reset the UI
downloading = NO;
[self downloadFiles];
}
// Download handler
- (void)downloadFiles
{
if ([_assetsToDownload count] > 0)
{
// Acquire the appropriate downloadTask and respond appropriately to the user's selection
NSURLSessionDownloadTask * downloadTask = [_assetsToDownload[0] downloadTask];
if (downloadTask.state == NSURLSessionTaskStateCompleted)
{
// Download is complete. Play movie.
// NSURL *movieURL = [NSURL fileURLWithPath:[_assetsToDownload[0] localPath]];
}
else if (downloadTask.state == NSURLSessionTaskStateSuspended)
{
// If suspended and not already downloading, resume transfer.
if (!downloading)
{
[self showHUD:[NSString stringWithFormat:@"Downloading %@",[_assetsToDownload[0] assetName]]];
[downloadTask resume];
downloading = YES;
}
}
else if (downloadTask.state == NSURLSessionTaskStateRunning)
{
// If already downloading, pause the transfer.
[downloadTask suspend];
downloading = NO;
}
}
}
- (void)downloadAssets
{
_assets = [self retreiveAssets]; // Getting the resource details from the database
if (![_assets count])
{
// Hide progress
}
[self addAssetDownload];
[self downloadFiles];
}
@end
有时它下载第一个文件并停在那里,下一次它不会下载任何东西。直到现在我才发现这个问题,因为这个问题我浪费了将近一天的时间。请帮我找出问题所在。提前感谢。当使用后台会话时,旧的下载请求可以在会话之间保留。您是否尝试过使用
getTasksWithCompletionHandler
检查旧的、未完成的后台任务?我经历了一段时间,直到我意识到,当我的应用程序启动时,它可能会在旧的后台请求后被积压。如果您在后台会话中有任何无效请求,则可以对所有内容进行一点备份
另外,您的应用程序代理是否正在处理handleEventsForBackgroundURLSession
方法,重新实例化后台会话并保存传递给您的应用程序的completionHandler
?您的NSURLSession
的委托是否调用该完成处理程序(可能在urlsessiondifinisheventsforbackgroundurlsession:
方法中)?您要确保清理这些后台会话。我在您的代码片段中没有看到任何这种方法,但为了简洁起见,您可能省略了它
关于这一点的讨论可在《指南》的背景转移注意事项部分找到。WWDC 2013视频播放约40分钟后也显示了这一示例。使用后台会话时,旧的下载请求可以在会话之间持续。您是否尝试过使用getTasksWithCompletionHandler
检查旧的、未完成的后台任务?我经历了一段时间,直到我意识到当我的应用程序启动时,它可以