Comment déterminer la taille (en octets) d'un téléchargement de fichier en utilisant NSURLConnection?
-
18-09-2019 - |
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);
}
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]);
}