Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
253 views
in Technique[技术] by (71.8m points)

iphone - NSURLConnection download large file (>40MB)

I need to download large file (i.e. > 40MB) to my application from server, this file will be ZIP or PDF. I achieved it using NSURLConnection, that works well if the file is smaller other wise it download a part of the fill and the execution has stopped. for example I tried to download 36MB PDF file, but but 16MB only downloaded. pls help me to know the reason? how to fix it?

FYI: Implementation File

#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 %@' : 
 %@ ", 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

Header File:

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

Thank you,

Updated: This happens because of my downloadable file was in shared hosting which having the download limitations. After I moved that file to dedicated server that working fine. and also I tried to download some other files like videos from some other sites, that also working fine. So, if you having problem like partial download, don't only stick with the code, check the server too

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are currently keeping all downloaded data in a NSMutableData object which is kept within the RAM of your device. That will, depending on the device and the available memory, at some point trigger a memory warning or even a crash.

To get such large downloads to work, you will have to write all downloaded data directly to the filesystem.

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...