NSURL下载大文件 (>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

谢谢你,

更新:之所以会出现这种情况,是因为我的可下载文件位于共享主机中,具有下载限制。在我把那个文件移到专用服务器后,它工作得很好。我还试着从其他网站下载一些其他文件,比如视频,效果也很好。因此,如果你有部分下载之类的问题,不要只使用代码,也要检查服务器

您当前将所有下载的数据保存在NSMutableData对象中,该对象保存在设备的RAM中。根据设备和可用内存的不同,这将在某个时刻触发内存警告甚至崩溃。

要使如此大的下载量发挥作用,您必须将所有下载的数据直接写入文件系统。

-(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];
}

我遇到了同样的问题,似乎找到了一些解决方案。

在您的头文件中声明:

NSMutableData *webData;
NSFileHandle *handleFile;

downloadFileFromURL上的.m文件中,当您获得连接时,启动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];

我现在正在尝试,希望它能起作用。。

之所以会发生这种情况,是因为我的可下载文件位于共享主机中,具有下载限制。在我把那个文件移到专用服务器后,它工作得很好。我还试着从其他网站下载一些其他文件,比如视频,效果也很好。

所以,如果你有部分下载之类的问题,不要只使用代码,还要检查服务器。

如果您愿意使用asi-http请求,它会非常简单。

结账https://github.com/steipete/PSPDFKit-Demo以asi为例。

就这么简单:

    // 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]);
    }];

相关内容

  • 没有找到相关文章

最新更新