NSURLConnectionを使用して、ファイルのダウンロードのサイズ(バイト単位)を決定する方法は?
-
18-09-2019 - |
質問
私はNSURLConnection(GET)を使用して、私のアプリに(バイト単位)をダウンロードしていたファイルのサイズを知っておく必要があります。ここでは、それは場合に役立ちます私のバイトは以下のコードを受け取っています。私が知っている必要があり、私は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);
}
解決
[データ長]あなたが探している姿を与えるべきであるバイト単位でデータのサイズを返しています。
しかし、NSDataのは-writeToFileを提供します:アトミック:と-writeToFile:オプション:ディスクにデータを書き込むためのエラー方法あなたがあなた自身のファイルI / Oを書いているので、なぜ私にはわからない。
他のヒント
私は、コードは、AppleからSimpleURLConnectionsサンプルコードからであると考えています。ここでは、AppleのNSURLConnectionメソッドからの直接の引用である「:didReceiveData:接続は、」
「デリゲートは、連結する必要があります 各データオブジェクトの内容が配信します 以下のための完全なデータを構築します URL負荷。」
のNSDataは、それが一度にすべてを書き込み、ファイルへのインクリメンタル書き込みを行うためのメソッドを提供していないので、私はNSOutputStreamにインクリメンタルに書き込み、この方法は、ここでFILESTREAMという名前の、正しいと思います。 「:didReceiveData:接続」、全体ではなく、接続のためのデータの全体の長さ、このコードでDATALENGTHを使用すると、唯一の1回の呼び出しで、デリゲートにNSURLConnectionから送られてきたデータの長さを返します。この私が追加した余分な特性を達成するには:
@property (nonatomic, assign) long long dataWrittenForWholeConnection;
@property (nonatomic, assign) long long dataLengthOfWholeConnection;
に関連して:didReceiveResponse:私は、全体の接続のための受信データのファイルサイズの正確な推定値を得るためにNSURLResponse方法expectedContentLengthを使用
。self.dataWrittenForWholeConnection = 0;
self.dataLengthOfWholeConnection = [httpResponse expectedContentLength];
の接続で:didReceiveData:私は次のように変更されます:
// 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);
}
接続の終わりまでに、これが本当である必要があります:
assert(dataWrittenForWholeConnection == dataLengthOfWholeConnection);
ここでは本当に何が起こっているかを示すために私の修正と同じSimpleURLConnectionsコードからプリントアウトがあります:
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.
また、NSOutputStream方法「書き込み:maxLengthの」リターン「は、実際に書き込まれたバイト数」、何らかの理由で、それは、単一のコール内で一度にすべてのデータを書き込むことがないことを選択することができるので、「:didReceiveData:接続」 、ループはこれをチェックする間、DOのように使用/。しかし、この例では、それは、反復しながら、シングル/ DO内のすべてのデータを書き込みます。
また、あなたの代わりにNSFileHandleを使用することができ、これは常に、各接続で送信された全データを書き込みます:didReceiveDataは:呼び出し、またそれはインクリメンタルです。書き込みデータは、ことに注意してください:。同期である
- (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]);
}