Подтвердить что ты не робот

NSURLConnection загрузить большой файл (> 40MB)

Мне нужно загрузить большой файл (то есть > 40 МБ) в мое приложение с сервера, этот файл будет ZIP или PDF. Я достиг этого с помощью NSURLConnection, который хорошо работает, если файл меньше другого, он загружает часть заполнения, и выполнение останавливается. например, я попытался загрузить 36MB PDF файл, но только 16 МБ загружался. PLS помочь мне узнать причину? как это исправить?

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

Спасибо,

Обновлено: Это происходит из-за того, что мой загружаемый файл находился в общем хостинге, который имеет ограничения на скачивание. После того, как я переместил этот файл на выделенный сервер, который работает нормально. а также я попытался загрузить некоторые другие файлы, такие как видео с некоторых других сайтов, которые также отлично работают. Итак, если у вас проблемы с частичной загрузкой, не только придерживайтесь кода, проверьте сервер тоже

4b9b3361

Ответ 1

Это происходит из-за того, что мой загружаемый файл находился в общем хостинге, который имеет ограничения на скачивание. После того, как я переместил этот файл на выделенный сервер, который работает нормально. а также я попытался загрузить некоторые другие файлы, такие как видео с некоторых других сайтов, которые также отлично работают.

Итак, если у вас проблемы с частичной загрузкой, не только придерживайтесь кода, проверьте сервер тоже.

Ответ 2

В настоящее время вы сохраняете все загруженные данные в объекте 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];
}

Ответ 3

У меня была такая же проблема, и, похоже, я обнаружил какое-то решение.

В вашем файле заголовка объявите:

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

Я пытаюсь сделать это прямо сейчас, надеюсь, что это сработает.

Ответ 4

Если вы хотите использовать asi-http-request, это намного проще.

Просмотрите 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]);
    }];