2011-08-10 1 views
2

Je me demande dans quelles conditions un objet NSHTTPURLResponse n'aura pas de clé @ "Content-Length"? Est-il normal/normal de ne pas avoir cette clé?`[[response allHeaderFields] objectForKey: @" Content-Length "]` est-il nul?

J'essaie quelque chose avec le SDK de Dropbox et je me suis rendu compte que

[[response allHeaderFields] objectForKey:@"Content-Length"] 

retours nil et est à l'origine downloadProgress être infinie:

NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue]; 
    downloadProgress = (CGFloat)bytesDownloaded/(CGFloat)contentLength; 

Est-il possible que je puisse faire la réponse avoir cette clé?

BTW: C'est la réponse que je reçois

(gdb) po [response allHeaderFields] 
{ 
    "Cache-Control" = "max-age=0"; 
    Connection = "keep-alive"; 
    "Content-Encoding" = gzip; 
    "Content-Type" = "text/plain; charset=UTF-16LE"; 
    Date = "Wed, 10 Aug 2011 06:21:43 GMT"; 
    Etag = 228n; 
    Pragma = public; 
    Server = dbws; 
    "Transfer-Encoding" = Identity; 
} 

EDIT (travail-arounded):

Comme l'a dit @Mitchell. Les serveurs ne renvoient pas toujours une telle clé. (Serveurs étranges de DropBox, pour .png oui, pour les fichiers txt parfois pas: /) Ainsi, afin de calculer le downloadProgress d'un fichier que j'ai modifié (arounded travail) la source:

//In DBRequest.m 
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { 
    ... 
    bytesDownloaded += [data length]; 
    //start of modification 
    //Server might not contain @"Content-Length" key, 
    //in that case use the downloadedBytes. Is better 
    //than having an infinite value because it could 
    //be handled by DBRestClient's delegate. (If not 
    //it will have the same effect as infinite) 
    if ([response expectedContentLength] == NSURLResponseUnknownLength) { 
     downloadProgress = (CGFloat)bytesDownloaded; 
    }else{ 
     NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue]; 
     downloadProgress = (CGFloat)bytesDownloaded/(CGFloat)contentLength; 
    } 
    //end of modification 
    if (downloadProgressSelector) { 
     [target performSelector:downloadProgressSelector withObject:self]; 
    } 
} 

Et depuis J'ai la taille d'un fichier à partir des métadonnées que je peux faire:

- (void)restClient:(DBRestClient *)client loadProgress:(CGFloat)progress forFile:(NSString *)destPath { 
    if (progress > 1) {//Work-around: This means the progress is not a 
     progress = progress/((CGFloat)(metadataOfTheFile.totalBytes)); 
    } 
    ... update the progress bar here 
} 
+3

De la documentation, nous pouvons voir qu'il ya une méthode qui expectedContentLength de peut retourner NSURLResponseUnknownLength si la longueur ne peut être déterminée. Avez-vous essayé cela? –

+0

Il semble également que vous affectez NSInteger contentLength à la valeur du pointeur de NSNumber, car vous ne pouvez pas stocker les types primitifs dans NSDictionary. Changez cela en NSNumber *. –

Répondre

3

Si vous vous souvenez que, parfois, les téléchargements en safari ou votre navigateur de choix n'ont pas une barre de progression soit, la longueur est pas déterminée . Dans ce cas particulier, un fileur de chargement est la meilleure chose à montrer. Cela dépend entièrement du fait que le serveur renvoie la longueur du contenu, ce qui est facultatif.

Honnêtement, je ne sais pas pourquoi il ne retourne pas cette information, c'est peut-être à cause de la gamme de contenu ou d'une autre variable qu'il décide de ne pas le révéler.

Vous devrez peut-être chercher ailleurs pour obtenir cette propriété, mais la meilleure recommandation est d'être prudent, plutôt que d'être désolé et d'éviter toutes les erreurs NaN.

+0

OU moins idéalement forcer la longueur de contenu, car l'index du répertoire dropBox devrait afficher la taille du fichier. –

+0

En effet, le serveur pourrait ne pas retourner cette information. J'ai réalisé que les serveurs Dropbox retournent "Content-Length" pour les images mais pas pour le fichier texte (* .txt) pas au moins avec les fichiers que j'essaie. J'ai mis en place une solution pour obtenir le pourcentage téléchargé :) – nacho4d

1

Il est autorisé que HTTP n'ait pas de champ Content-Length, c'est facultatif. Donc, vous devez gérer:

NSNumber *lengthNumber = [[response allHeaderFields] objectForKey:@"Content-Length"]; 
NSUInteger contentLength = [lengthNumber unsignedIntegerValue]; 
if (contentLength == 0) { 
    // Calculate progress. 
} else { 
    // Can't calculate progress. 
} 
+0

Etes-vous sûr que c'est correct? Contentlength doit être différent de zéro pour calculer la progression. –

+0

@Mitchell Currie: Voir [RFC 2616] (http://www.ietf.org/rfc/rfc2616.txt), sections 4.4 pour les détails sanglants, ou section 14.13 juste pour le champ 'Content-Length'.La partie essentielle est: * "Dans HTTP, DEVRAIT être envoyé chaque fois que la longueur du message peut être déterminée avant le transfert " *: parfois l'application ne peut pas savoir combien de données elle enverra, et c'est à ce moment que le champ Content-Length est laissé de côté. Ceci est utilisé par exemple pour le streaming multimédia. – DarkDust