Comment déterminer la taille (en octets) d'un téléchargement de fichier en utilisant NSURLConnection?

StackOverflow https://stackoverflow.com/questions/2205167

Question

Je dois connaître la taille du fichier que je télécharge (en octets) dans mon application avec NSURLConnection (GET). Voici mes octets du code ci-dessous recieved si ça aide. Ce que je dois savoir est comment obtenir le filesize en octets afin que je puisse l'utiliser pour afficher un UIProgressView.

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
// A delegate method called by the NSURLConnection as data arrives.  We just 
// write the data to the file.
{
#pragma unused(theConnection)
    NSInteger       dataLength;
    const uint8_t * dataBytes;
    NSInteger       bytesWritten;
    NSInteger       bytesWrittenSoFar;

    assert(theConnection == self.connection);

    dataLength = [data length];
    dataBytes  = [data bytes];

    bytesWrittenSoFar = 0;
    do {
        bytesWritten = [self.fileStream write:&dataBytes[bytesWrittenSoFar] maxLength:dataLength - bytesWrittenSoFar];
        assert(bytesWritten != 0);
        if (bytesWritten == -1) {
            [self _stopReceiveWithStatus:@"File write error"];
            break;
        } else {
            bytesWrittenSoFar += bytesWritten;

    } while (bytesWrittenSoFar != dataLength);
}
Était-ce utile?

La solution

[longueur des données] ne retourne la taille des données en octets qui devrait vous donner le chiffre que vous cherchez.

Mais NSData fournit -writeToFile: atomiquement: et -writeToFile: Options: méthodes d'erreur pour les données d'écriture sur le disque donc je ne sais pas pourquoi vous écrivez votre propre fichier E / S

.

Autres conseils

Je crois que le code est du code exemple SimpleURLConnections d'Apple. Voici une citation directe de la méthode NSURLConnection d'Apple « connexion: didReceiveData: »

  "Le délégué

devrait concaténer la   le contenu de chaque objet de données livrées   pour construire les données complètes pour une   charge URL. "

NSData ne, donc je pense que les méthodes fournit pas d'écrire progressivement à un fichier, il écrit tout à la fois cette méthode d'écriture progressivement à un NSOutputStream, nommé ici fileStream, est correcte. En utilisant dataLength dans ce code ne retourne la longueur des données qui a été envoyé par le NSURLConnection au délégué dans un seul appel à la « connexion: didReceiveData: », pas la longueur totale des données pour toute la connexion. Pour y parvenir, j'ai ajouté des propriétés supplémentaires:

@property (nonatomic, assign)   long long dataWrittenForWholeConnection;
@property (nonatomic, assign)   long long dataLengthOfWholeConnection;

Dans le cadre: didReceiveResponse: J'utilisé la méthode NSURLResponse expectedContentLength pour obtenir l'estimation correcte de la taille du fichier de données de réception pour la connexion entière

.
self.dataWrittenForWholeConnection = 0;
self.dataLengthOfWholeConnection = [httpResponse expectedContentLength];

Dans le cadre: didReceiveData: J'ai changé les éléments suivants:

// bytes written for current "connection:didReceiveData:" call
bytesWrittenSoFar += bytesWritten;
// cumulative data written for connection so far
self.dataWrittenForWholeConnection += bytesWritten;

// also update the progress bar
if (self.dataLengthOfWholeConnection != NSURLResponseUnknownLength) {
    self.progressView.progress =
        ((float)self.dataWrittenForWholeConnection / (float)self.dataLengthOfWholeConnection);
}

A la fin de la connexion, cela devrait être vrai:

assert(dataWrittenForWholeConnection == dataLengthOfWholeConnection);

Voici l'impression du même code SimpleURLConnections avec mes modifications pour montrer ce qui se passe réellement:

connection:didReceiveResponse:
Full size of data is 8789 bytes

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.160200
1408 bytes of data were written, 1408 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.320401
1408 bytes of data were written, 2816 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.480601
1408 bytes of data were written, 4224 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.640801
1408 bytes of data were written, 5632 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.801001
1408 bytes of data were written, 7040 bytes so far

connection:didReceiveData:
Data has 1749 bytes
Progress bar is at: 1.000000
1749 bytes of data were written, 8789 bytes so far

connectionDidFinishLoading:
Connection Finished. 8789/8789 bytes of data were written.

En outre, la méthode NSOutputStream « écriture: maxLength: » renvoie « le nombre d'octets écrits », donc pour une raison quelconque, il peut choisir de ne pas écrire toutes les données à la fois dans un seul appel de « connexion: didReceiveData: » , donc l'utilisation de la boucle do / while pour vérifier cela. Mais dans cet exemple, il écrit toutes les données en un seul do / while itération.

En outre, vous pouvez utiliser un NSFileHandle à la place, et cela toujours écrire l'ensemble des données envoyées à chaque connexion: didReceiveData: appel, aussi est incrémentale. Notez cependant que writeData:. Est synchrone

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // write data to file handler
    unsigned long long dataLength = [data length];

    NSLog(@"Writing %qu bytes at %qu bytes", dataLength, [self.fileHandle offsetInFile]);
    [self.fileHandle writeData:data];
    NSLog(@"Wrote %qu bytes, now at %qu bytes", dataLength, [self.fileHandle offsetInFile]);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top