iphone - mail - NSURLConnection descargar archivo grande(> 40MB)
mail drop iphone (4)
Necesito descargar un archivo grande (es decir,> 40 MB) a mi aplicación desde el servidor, este archivo será ZIP o PDF. Lo logré utilizando NSURLConnection , que funciona bien si el archivo es más pequeño, sino que descarga una parte del relleno y la ejecución se detiene. por ejemplo, intenté descargar un archivo PDF de 36 MB, pero solo 16 MB descargados. Por favor me ayude a saber la razón? ¿Como arreglarlo?
FYI: archivo de implementación
#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
Archivo de cabecera:
#import <UIKit/UIKit.h>
@interface ZipHandlerV1ViewController : UIViewController {
NSMutableData *webData;
NSString *url;
}
-(void) setRequestURL:(NSString*) requestURL;
@end
Gracias,
Actualizado: Esto sucede debido a que mi archivo descargable estaba en un alojamiento compartido con las limitaciones de descarga. Después de que moví ese archivo a un servidor dedicado, funcioné bien. También intenté descargar algunos otros archivos, como videos de otros sitios, que también funcionan bien. Por lo tanto, si tiene problemas como la descarga parcial, no solo se adhiera al código, también verifique el servidor
Actualmente mantiene todos los datos descargados en un objeto NSMutableData que se guarda dentro de la RAM de su dispositivo. Eso, según el dispositivo y la memoria disponible, en algún momento activará una advertencia de memoria o incluso un bloqueo.
Para que funcionen descargas tan grandes, deberá escribir todos los datos descargados directamente en el sistema de archivos.
-(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];
}
Esto sucede debido a que mi archivo descargable estaba en un alojamiento compartido que tiene las limitaciones de descarga. Después de que moví ese archivo a un servidor dedicado, funcioné bien. También intenté descargar algunos otros archivos, como videos de otros sitios, que también funcionan bien.
Por lo tanto, si tiene problemas como la descarga parcial, no solo se adhiera al código, también verifique el servidor.
Si estás dispuesto a usar asi-http-request, es mucho más fácil.
Echa un vistazo a https://github.com/steipete/PSPDFKit-Demo para un ejemplo de trabajo con asi.
Es tan fácil como esto:
// 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]);
}];
Tuve el mismo problema, y parece que descubrí alguna solución.
En su archivo de cabecera declare:
NSMutableData *webData;
NSFileHandle *handleFile;
En su archivo .m en downloadFileFromURL
cuando obtenga la conexión, inicie 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];
}
luego, en didReceiveData
en lugar de didReceiveData
datos a la memoria, escríbalos en el disco, así:
- (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];
}
}
cuando la descarga finalice en connectionDidFinishLoading
agregue estas líneas para escribir el archivo y liberar la conexión:
[handleFile writeData:webData];
[webData release];
[theConnection release];
Lo estoy intentando ahora mismo, espero que funcione ...