2014-05-10 5 views
6

Ho dovuto affrontare uno strano problema. Carico file da Internet utilizzando NSURLSession e NSURLSessionDownloadTask. Ecco il codicetotalBytesExpectedToWrite è -1 in NSURLSessionDownloadTask

NSURLSessionConfiguration *sessionConfiguration = 
[NSURLSessionConfiguration backgroundSessionConfiguration:kSessionId]; 
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration 
              delegate:self 
             delegateQueue:[NSOperationQueue new]]; 
NSURL *url = [NSURL URLWithString:urlString]; 
NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request]; 
[downloadTask resume]; 

La mia classe è dichiarata come NSURLSessionDownloadDelegate e ottengo bene callback. Ma quando il sistema chiama il metodo delegato

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite 
{ 
    NSLog(@"totalBytesExpectedToWrite: %lld", totalBytesExpectedToWrite); 
    NSLog(@"%lld", totalBytesWritten); 
} 

totalBytesExpectedToWrite sempre uguale -1 e non ho capacità di mostrare un progresso utente perché non so la dimensione del file di download.

Potrebbe chiedermi dove ho fatto un errore?

+1

Potrebbe essere un problema di server in cui non sta inviando correttamente l'intestazione 'Content-Length' . Se si utilizza lo stesso URL nel browser, il browser mostra i progressi necessari? – rmaddy

risposta

10

-1 è NSURLSessionTransferSizeUnknown, il che significa che il server HTTP non ha fornito un header "Content-Length" (ed i dati vengono inviati tramite "Transfer-Encoding: Chunked").

Probabilmente non c'è molto che tu possa fare. Si potrebbe provare se la soluzione da https://stackoverflow.com/a/12599242/1187415 funziona nel vostro caso così:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:anURL]; 
[request addValue:@"" forHTTPHeaderField:@"Accept-Encoding"]; 
2

Il servizio web potrebbe non fornire la dimensione totale nel campo di intestazione Content-Length.

Se non viene fornita la dimensione totale, l'app non è in grado di conoscere la lunghezza e fornisce una barra di avanzamento.

Controllare cosa viene dal server Web con un analizzatore come Charles Proxy.

0

Il Content-Length può essere non 0 e totalBytesExpectedToWrite: -1

//TRACK PROGRESS - MOVED DOWN as also used in BACKGROUND REFRESH > DOWNLOAD FILE > CALL DELEGATE 
-(void)URLSession:(NSURLSession *)session 
    downloadTask:(NSURLSessionDownloadTask *)downloadTask 
    didWriteData:(int64_t)bytesWritten 
totalBytesWritten:(int64_t)totalBytesWritten 
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite 
{ 
    //to see response header 
    NSLog(@"downloadTask.response:%@\n", downloadTask.response); 

// { status code: 200, headers { 
//  "Cache-Control" = "no-cache"; 
//  "Content-Disposition" = "attachment; filename=Directory.zip"; 
//  "Content-Encoding" = gzip; 
//  "Content-Length" = 33666264; 
//  "Content-Type" = "application/octet-stream"; 
//  Date = "Tue, 27 Oct 2015 15:50:01 GMT"; 
//  Expires = "-1"; 
//  Pragma = "no-cache"; 
//  Server = "Microsoft-IIS/8.5"; 
//  "X-AspNet-Version" = "4.0.30319"; 
//  "X-Powered-By" = "ASP.NET"; 
// } } 

    NSDictionary *responseHeaders = ((NSHTTPURLResponse *)downloadTask.response).allHeaderFields; 
    NSString * contentLengthString = responseHeaders[@"Content-Length"]; 
    double contentLengthDouble = 0.0f; 

    if (contentLengthString) { 
     NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; 
     NSNumber *contentLengthNumber = [f numberFromString:contentLengthString]; 
     contentLengthDouble = [contentLengthNumber doubleValue]; 
    }else{ 

    } 
    NSLog(@"contentLengthString:[%@]", contentLengthString); 
    //You can get progress her 

    NSLog(@"bytesWritten:%lld", bytesWritten); 
    NSLog(@"totalBytesWritten:%lld", totalBytesWritten); 

    //DONT USE CAN BE ALWAYS -1 for Gzip 
    NSLog(@"totalBytesExpectedToWrite:%lld", totalBytesExpectedToWrite); 

    //avoid DIV by 0 
    if (contentLengthDouble > 0.0) { 
     double percentage1 = (totalBytesWritten/contentLengthDouble); 
     double percentage = percentage1 * 100.0; 
     NSLog(@"PERCENTAGE DOWNLOADED:[%f%%]", percentage); 
    }else{ 
     NSLog(@"PERCENTAGE DOWNLOADED:[contentLengthDouble is 0]"); 
    } 

    NSLog(@"========="); 
} 

Quello che segue è uscita più e più volte come zip viene scaricato.

ma totalBytesExpectedToWrite: -1

Quindi è necessario controllare Content-Length in downloadTask.response

2015-10-27 16:04:18.580 ClarksonsDirectory[89873:15495901] downloadTask.response:<NSHTTPURLResponse: 0x7f9eabaae750> { URL: http://asset10232:50/api/1/dataexport/ios/?lastUpdatedDate=01012014000000 } { status code: 200, headers { 
    "Cache-Control" = "no-cache"; 
    "Content-Disposition" = "attachment; filename=Directory.zip"; 
    "Content-Encoding" = gzip; 
    "Content-Length" = 33666264; 
    "Content-Type" = "application/octet-stream"; 
    Date = "Tue, 27 Oct 2015 16:03:55 GMT"; 
    Expires = "-1"; 
    Pragma = "no-cache"; 
    Server = "Microsoft-IIS/8.5"; 
    "X-AspNet-Version" = "4.0.30319"; 
    "X-Powered-By" = "ASP.NET"; 
} } 

contentLengthString:[33666264] 
bytesWritten:47278 
totalBytesWritten:33606690 
totalBytesExpectedToWrite:-1 
PERCENTAGE DOWNLOADED:[99.823045%]