1

我有一个问题,我真的可以通过一些帮助来解决

我正在使用 NSURLconnection 下载一个大文件(27MB)。当没有网络中断时,代码可以正常工作。为了解决网络问题和仅部分下载的文件,我添加了代码来检查下载了多少文件,然后使用服务器请求下载丢失的部分。

如果我下载部分文件,停止程序运行然后再次运行,则代码可以正常工作 - 然后下载从它停止的地方开始并且我有完整的文件。

但是,如果我在没有停止程序的情况下再次点击下载按钮,那么 didReceiveData 只会被调用一次,并且只向文件添加 200KB,它告诉我文件已成功下载。

请帮忙 - 我花了很长时间试图弄清楚我做错了什么。

下面的代码:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;

    NSLog(@"Response code = %d",httpResponse.statusCode );
     file = [NSFileHandle fileHandleForUpdatingAtPath:filename] ;// file is in .h


    if (file)   {
       [file seekToEndOfFile];
    }

}




- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{

    if (file)  {

        [file seekToEndOfFile];
        NSLog(@"file is %@",file);

    }

    [self.file writeData:data];
 }




- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{

    if([[NSFileManager defaultManager] fileExistsAtPath:filename])
    {
       [file closeFile];
        file = nil;
        theConnection = nil;
        filename = nil;
        theRequest = nil;
     }
     NSLog(@"Connection failed! Error - %@ %@",
     [error localizedDescription],
     [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{

    [file closeFile];
    file = nil;
    theConnection = nil;
    filename = nil;

}


- (IBAction)downloadFile:(id)sender {


    filename = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:movie1]; // filename is in .h file

    theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:movieDownload1]                                          cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];

    NSUInteger downloadedBytes = 0;
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:filename]) {
        NSError *error = nil;
        NSDictionary *fileDictionary = [fm attributesOfItemAtPath:filename error:&error];
        if (!error && fileDictionary)
        downloadedBytes = [fileDictionary fileSize];
    } else {
        [fm createFileAtPath:filename contents:nil attributes:nil];
    }

    if (downloadedBytes > 0) {
         NSString *requestRange = [NSString stringWithFormat:@"bytes=%d-",downloadedBytes];
        [theRequest setValue:requestRange forHTTPHeaderField:@"Range"];
    }

    theConnection = nil;
    theConnection = [NSURLConnection connectionWithRequest:theRequest delegate:self];

   }
4

1 回答 1

0

您可以尝试以下代码片段,而不是在 didReceiveResponse 和 didReceiveData 中使用 seekToEndOfFile。它对我来说效果很好。

- (id)initWithURL:(NSString *)downloadString
{
    if (![super init])
        return nil;

    // Construct the URL to be downloaded
    self.downloadURL = [[NSURL alloc]initWithString:downloadString];
    self.downloadData = [[NSMutableData alloc] init];
    self.downloadedFilename   =   [[self.downloadURL path] lastPathComponent];

    [self downloadFile];

    return self;
}

-(void) downloadFile
{
    // set the filePath
    docFolderPath = [NSHomeDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: @"Documents/%@", self.downloadedFilename]];

    self.downloadStream = [NSOutputStream outputStreamToFileAtPath:docFolderPath append:NO];

    if (!self.downloadStream)
    {
        self.error = [NSError errorWithDomain:[NSBundle mainBundle].bundleIdentifier
                                         code:-1
                                     userInfo:@{@"message": @"Unable to create      NSOutputStream", @"function" : @(__FUNCTION__), @"path" : self.downloadedFilename}];

        return;
    }
    [self.downloadStream open];

    self.downloadConnection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self];
    [self.downloadConnection start];
}

//code snippet for the Resume functionality after your downloading gets paused/cancel

-(void) resumeInterruptedDownload
{
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:docFolderPath])
    {
        NSError *error = nil;
        NSDictionary *fileDictionary = [fm attributesOfItemAtPath:docFolderPath
                                                            error:&error];
        if (!error && fileDictionary)
            self.downloadedBytes = [fileDictionary fileSize];


    } else
    {
        [fm createFileAtPath:docFolderPath contents:nil attributes:nil];
    }


    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];

    // Define the bytes we wish to download.

    if(self.downloadedBytes != 0)
    {
        NSString *range = [NSString stringWithFormat:@"bytes=%i-", self.downloadedBytes];
        [request setValue:range forHTTPHeaderField:@"Range"];
    }

    // Data should immediately start downloading after the connection is created.

    self.downloadConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:TRUE];
}

对于 Mbs 中的大文件,它对我来说非常有效,但对于 Kbs 中的小文件,它有时会失败。您不必在所有这些 NSURLConnection 的委托方法中尝试太多。您可以做的一件事是为每个状态设置宏,即取消、暂停、下载、已下载,这样您就可以知道何时要恢复下载。您也可以尝试以下http://nachbaur.com/blog/resuming-large-downloads-with-nsurlconnection

我知道现在回复为时已晚,但我刚刚进入 IOS。如果你尝试这个,请让我知道它是否有效。谢谢 :) :)

于 2014-01-03T12:35:40.037 回答