2014-05-10 1 views
6

J'ai rencontré un problème étrange. Je charge le fichier à partir d'Internet en utilisant NSURLSession et NSURLSessionDownloadTask. Voici le codetotalBytesExpectedToWrite est -1 dans 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]; 

Ma classe est déclarée comme NSURLSessionDownloadDelegate et je reçois bien callbacks. Mais lorsque le système appelle la méthode délégué

- (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 toujours égale -1 et je n'ai pas la possibilité de montrer un progrès à l'utilisateur parce que je ne sais pas la taille du fichier de téléchargement.

Pourriez-vous m'indiquer où j'ai fait une erreur?

+1

Il pourrait être un problème de serveur où il n'envoie pas correctement l'en-tête 'Content-Length' . Si vous utilisez la même URL dans votre navigateur, votre navigateur affiche-t-il des progrès corrects? – rmaddy

Répondre

10

-1 est NSURLSessionTransferSizeUnknown, ce qui signifie que le serveur http n'a pas fourni un en-tête "Content-Length" (et les données sont envoyées à l'aide "Transfer-Encoding: chunked").

Il n'y a probablement pas grand-chose à faire. Vous pouvez essayer si la solution de contournement de https://stackoverflow.com/a/12599242/1187415 fonctionne dans votre cas ainsi:

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

Le service Web ne peut pas être fourni la taille totale dans le champ d'en-tête Content-Length.

Si la taille totale n'est pas fournie, votre application ne peut en connaître la longueur et cela fournit une barre de progression.

Vérifiez ce qui provient du serveur Web avec un analyseur tel que Charles Proxy.

0

Le Content-Length peut être non 0 et 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(@"========="); 
} 

Ce qui suit est sortie à plusieurs reprises que zip est téléchargé.

mais totalBytesExpectedToWrite: -1

Vous devez vérifier Content-Length dans 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%] 
Questions connexes