如何确定使用 NSURLConnection 下载的文件的大小(以字节为单位)?

发布于 2024-08-20 12:22:31 字数 1054 浏览 12 评论 0原文

我需要知道使用 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);
}

I need to know the size of the file I am downloading (in bytes) into my app using NSURLConnection (GET). Here is my bytes recieved code below if it helps. What I need to know is how to get the filesize in bytes so that I can use it to show a 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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜巴黎 2024-08-27 12:22:32

[数据长度]确实返回数据的大小(以字节为单位),这应该为您提供您正在寻找的数字。

但是 NSData 提供了 -writeToFile:atomically: 和 -writeToFile:options:error 方法将数据写入磁盘,所以我不知道你为什么要编写自己的文件 I/O。

[data length] does return the size of the data in bytes which should give you the figure you're looking for.

But NSData provides -writeToFile:atomically: and -writeToFile:options:error methods for writing data to disk so I don't know why you're writing your own file I/O.

薆情海 2024-08-27 12:22:32

我相信该代码来自 Apple 的 SimpleURLConnections 示例代码。这里直接引用苹果的 NSURLConnection 方法“connection:didReceiveData:”

“委托应该连接
传递的每个数据对象的内容
建立完整的数据
网址加载。”

不提供增量写入文件的方法,它会一次性写入所有内容,因此我认为这种增量写入 NSOutputStream(此处名为 fileStream)的方法是正确的。在此代码中使用 dataLength 只会返回在一次调用“connection:didReceiveData:”中从 NSURLConnection 发送到委托的数据长度,而不是整个连接的数据总长度。为了实现此目的,我添加了额外的属性:

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

在连接中 。 :didReceiveResponse:我使用 NSURLResponse 方法预期内容长度来获取整个连接的接收数据文件大小的正确估计

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]);
}

I believe the code is from the SimpleURLConnections sample code from Apple. Here is a direct quote from Apple's NSURLConnection method "connection:didReceiveData:"

"The delegate should concatenate the
contents of each data object delivered
to build up the complete data for a
URL load."

NSData does not provide methods to write incrementally to a file, it writes it all at once, so I think this method of writing incrementally to an NSOutputStream, here named fileStream, is correct. Using dataLength in this code will only return the length of the data that has been sent from the NSURLConnection to the delegate in a single call to "connection:didReceiveData:", not the overall length of the data for the entire connection. To achieve this I have added extra properties:

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

In connection:didReceiveResponse: I used the NSURLResponse method expectedContentLength to obtain the correct estimate of the receiving data's file size for the whole connection.

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

In connection:didReceiveData: I changed the following:

// 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);
}

By the end of the connection, this should be true:

assert(dataWrittenForWholeConnection == dataLengthOfWholeConnection);

Here is the printout from the same SimpleURLConnections code with my modifications to show what is really happening:

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.

Also, the NSOutputStream method "write:maxLength:" returns "the number of bytes actually written", so for some reason it may choose not to write all the data at once within a single call of "connection:didReceiveData:", thus the use of the do/while loop to check for this. But in this example it writes all the data in a single do/while iteration.

Also, you can use an NSFileHandle instead, and this will always write the whole data sent with each connection:didReceiveData: call, also it's incremental. Note however that writeData: is synchronous.

- (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]);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文