我相信代码来自 Apple 的 SimpleURLConnections 示例代码。这是来自 Apple 的 NSURLConnection 方法“connection:didReceiveData:”的直接引用
“委托应连接交付的每个数据对象的内容,以构建 URL 加载的完整数据。”
NSData 没有提供增量写入文件的方法,它一次写入所有文件,所以我认为这种增量写入 NSOutputStream 的方法,这里命名为 fileStream,是正确的。在此代码中使用 dataLength 只会返回在一次调用“connection:didReceiveData:”中从 NSURLConnection 发送到委托的数据长度,而不是整个连接的数据总长度。为此,我添加了额外的属性:
@property (nonatomic, assign) long long dataWrittenForWholeConnection;
@property (nonatomic, assign) long long dataLengthOfWholeConnection;
在 connection: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 方法“write:maxLength:”返回“实际写入的字节数”,因此出于某种原因,它可能选择不在一次调用“connection:didReceiveData:”中一次写入所有数据,因此使用 do/while 循环来检查这一点。但在本例中,它在一次 do/while 迭代中写入所有数据。
此外,您可以使用 NSFileHandle 代替,这将始终写入每个连接发送的全部数据:didReceiveData:调用,它也是增量的。但是请注意 writeData: 是同步的。
- (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]);
}