NSURLConnection下载大文件(> 40MB)

我需要从服务器下载大文件(即大于40MB)到我的应用程序,这个文件将是ZIP或PDF。 我使用NSURLConnection实现它,如果文件较小,则工作正常。否则,下载部分填充并停止执行。 例如我试图下载36MB的PDF文件,但只下载了16MB。 请帮我知道原因? 如何解决它?

FYI:实施文件

#import "ZipHandlerV1ViewController.h" @implementation ZipHandlerV1ViewController - (void)dealloc { [super dealloc]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (void)viewDidLoad { UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]; [mainView setBackgroundColor:[UIColor darkGrayColor]]; UIButton *downloadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [downloadButton setFrame:CGRectMake(50, 50, 150, 50)]; [downloadButton setTitle:@"Download File" forState:UIControlStateNormal]; [downloadButton addTarget:self action:@selector(downloadFileFromURL:) forControlEvents:UIControlEventTouchUpInside]; [mainView addSubview:downloadButton]; [self setRequestURL:@"http://www.mobileveda.com/r_d/mcps/optimized_av_allpdf.pdf"]; [self.view addSubview:mainView]; [super viewDidLoad]; } - (void)viewDidUnload { [super viewDidUnload]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } -(void) setRequestURL:(NSString*) requestURL { url = requestURL; } -(void) downloadFileFromURL:(id) sender { NSURL *reqURL = [NSURL URLWithString:url]; NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:reqURL]; NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; if (theConnection) { webData = [[NSMutableData data] retain]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error !" message:@"Error has occured, please verify internet connection" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; [alert release]; } } -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [webData setLength:0]; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [webData appendData:data]; } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { NSString *fileName = [[[NSURL URLWithString:url] path] lastPathComponent]; NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *folder = [pathArr objectAtIndex:0]; NSString *filePath = [folder stringByAppendingPathComponent:fileName]; NSURL *fileURL = [NSURL fileURLWithPath:filePath]; NSError *writeError = nil; [webData writeToURL: fileURL options:0 error:&writeError]; if( writeError) { NSLog(@" Error in writing file %@' : \n %@ ", filePath , writeError ); return; } NSLog(@"%@",fileURL); } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error !" message:@"Error has occured, please verify internet connection.." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; [alert release]; } @end 

头文件:

 #import <UIKit/UIKit.h> @interface ZipHandlerV1ViewController : UIViewController { NSMutableData *webData; NSString *url; } -(void) setRequestURL:(NSString*) requestURL; @end 

谢谢,

更新: 发生这种情况是因为我的可下载文件在共享主机中,具有下载限制。 我将该文件移动到专用服务器,工作正常后。 也试图从其他网站下载一些其他文件,如video也工作正常。 所以,如果你有部分下载的问题,不仅要坚持代码,也要检查服务器

您目前正在将所有下载的数据保存在您的设备的RAM中的NSMutableData对象中。 这将取决于设备和可用的内存,在某些时候触发内存警告甚至崩溃。

为了获得如此大的下载量,您必须将所有下载的数据直接写入文件系统。

 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { //try to access that local file for writing to it... NSFileHandle *hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath]; //did we succeed in opening the existing file? if (!hFile) { //nope->create that file! [[NSFileManager defaultManager] createFileAtPath:self.localPath contents:nil attributes:nil]; //try to open it again... hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath]; } //did we finally get an accessable file? if (!hFile) { //nope->bomb out! NSLog("could not write to file %@", self.localPath); return; } //we never know - hence we better catch possible exceptions! @try { //seek to the end of the file [hFile seekToEndOfFile]; //finally write our data to it [hFile writeData:data]; } @catch (NSException * e) { NSLog("exception when writing to file %@", self.localPath); result = NO; } [hFile closeFile]; } 

我有同样的问题,似乎我发现了一些解决scheme。

在你的头文件中声明:

 NSMutableData *webData; NSFileHandle *handleFile; 

在你的.m文件中downloadFileFromURL当你获得连接时启动NSFileHandle:

 if (theConnection) { webData = [[NSMutableData data] retain]; if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; } handleFile = [[NSFileHandle fileHandleForWritingAtPath:filePath] retain]; } 

然后在didReceiveData而不是将数据附加到内存中写入磁盘,如下所示:

 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [webData appendData:data]; if( webData.length > SOME_FILE_SIZE_IN_BYTES && handleFile!=nil) { [handleFile writeData:recievedData]; [webData release]; webData =[[NSMutableData alloc] initWithLength:0]; } } 

connectionDidFinishLoading上的下载完成时,添加以下行来写入文件并释放连接:

 [handleFile writeData:webData]; [webData release]; [theConnection release]; 

我正在尝试它,希望它的作品..

发生这种情况的原因是我的可下载文件在共享主机中,具有下载限制。 我将该文件移动到专用服务器,工作正常后。 也试图从其他网站下载一些其他文件,如video也工作正常。

所以,如果你有部分下载的问题,不仅要坚持代码,也要检查服务器。

如果你愿意使用asi-http-request,那要容易得多。

查看https://github.com/steipete/PSPDFKit-Demo以了解asi的一个工作示例&#x3002;

这很简单:

  // create request ASIHTTPRequest *pdfRequest = [ASIHTTPRequest requestWithURL:self.url]; [pdfRequest setAllowResumeForFileDownloads:YES]; [pdfRequest setNumberOfTimesToRetryOnTimeout:0]; [pdfRequest setTimeOutSeconds:20.0]; [pdfRequest setShouldContinueWhenAppEntersBackground:YES]; [pdfRequest setShowAccurateProgress:YES]; [pdfRequest setDownloadDestinationPath:destPath]; [pdfRequest setCompletionBlock:^(void) { PSELog(@"Download finished: %@", self.url); // cruel way to update [XAppDelegate updateFolders]; }]; [pdfRequest setFailedBlock:^(void) { PSELog(@"Download failed: %@. reason:%@", self.url, [pdfRequest.error localizedDescription]); }];