NSURLSessionDownloadTask - 下载但以错误结束

时间:2014-03-09 04:29:21

标签: objective-c nsurlsession

我正在尝试下载pdf文件。之前,当我使用完成处理程序块时,我能够在tmp位置看到该文件。然后我想显示下载进度,所以我实现了委托方法。但我现在可以看到进度条工作和正在下载的文件。但是一旦下载完成(写入的字节数/总字节数= 1),就会调用错误委托,并且tmp位置中没有文件。我错过了什么?下面是我的代码。我已在https://www.dropbox.com/s/vn5zwfwx9izq60a/trydownload.zip

上传了该项目
@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://aayudham.com/URLLoadingSystem.pdf"]];
    [downloadTask resume];

}

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    NSLog(@"%@",[error localizedDescription]);
}
-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    dispatch_async(dispatch_get_main_queue(), ^{
        _progressBar.progress = (double)totalBytesWritten/(double)totalBytesExpectedToWrite;
        double value =(double)totalBytesWritten/(double)totalBytesExpectedToWrite;
        NSLog(@"%f",value);
    });
}

-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{

}

-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
       NSError *error;
//getting docs dir path
NSArray * tempArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [tempArray objectAtIndex:0];

//adding folder path
NSString *appDir = [docsDir stringByAppendingPathComponent:@"/Reader/"];

NSFileManager *fileManager = [NSFileManager defaultManager];

if(![fileManager fileExistsAtPath:appDir])
{
    [fileManager createDirectoryAtPath:appDir withIntermediateDirectories:NO attributes:nil error:&error];
}


BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:[appDir stringByAppendingString:@"/demo.pdf"] error:&error];

NSLog(fileCopied ? @"Yes" : @"No");
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

3 个答案:

答案 0 :(得分:11)

@Rob感谢您的快速回复,这对我帮助很大。这是我的代码有效。希望它可以帮助某人。我能够获取实际的文件名,并使用原始名称将文件移动到我的文档目录。

-(void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;

    //getting application's document directory path
    NSArray * tempArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docsDir = [tempArray objectAtIndex:0];

    //adding a new folder to the documents directory path
    NSString *appDir = [docsDir stringByAppendingPathComponent:@"/Reader/"];

    //Checking for directory existence and creating if not already exists
    if(![fileManager fileExistsAtPath:appDir])
    {
        [fileManager createDirectoryAtPath:appDir withIntermediateDirectories:NO attributes:nil error:&error];
    }

    //retrieving the filename from the response and appending it again to the path
    //this path "appDir" will be used as the target path 
    appDir =  [appDir stringByAppendingFormat:@"/%@",[[downloadTask response] suggestedFilename]];

    //checking for file existence and deleting if already present.
    if([fileManager fileExistsAtPath:appDir])
    {
        NSLog([fileManager removeItemAtPath:appDir error:&error]?@"deleted":@"not deleted");
    }

    //moving the file from temp location to app's own directory
    BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:appDir error:&error];
    NSLog(fileCopied ? @"Yes" : @"No");

}

答案 1 :(得分:7)

didFinishDownloadingToURL中,您应该将文件从location移到某个更永久的地方(例如您的“文档”文件夹)。如果您稍后在临时位置查找该文件,我不会感到惊讶它不再存在。

正如the documentation所说,location定义如下:

  

临时文件的文件URL。由于该文件是临时文件,因此必须先打开文件进行读取,或者在从此委托方法返回之前将其移动到应用程序沙盒容器目录中的永久位置。

在从didFinishDownloadingToURL返回之前,您必须将文件移至新位置

答案 2 :(得分:3)

万一有人遇到了同样的问题,我想我会在这里发布我的解决方案。

我的问题是谓词方法在后台线程上触发,所以我发送到我的“文件io”线程,该线程处理任何文件写入,删除应用程序内的等。

这个问题是,一旦委托方法结束,临时文件就会被删除,这是在切换线程的那一刻发生的。因此,当我尝试访问我的文件io线程中的文件时,它已被删除。

我的解决方案是在委托方法中将文件解析为NSData,然后使用NSData在我的文件io线程中写入文件系统。