`[[response allHeaderFields] objectForKey:@"Content-Length"]` 为零?

发布于 2024-11-28 13:20:33 字数 2321 浏览 0 评论 0 原文

我想知道在什么条件下 NSHTTPURLResponse 对象不会有键 @"Content-Length" ?没有那把钥匙是正常的吗?

我正在尝试使用 dropbox SDK 进行某些操作,并且我意识到

[[response allHeaderFields] objectForKey:@"Content-Length"]

返回 nil 并导致 downloadProgress 无限:

 NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue];
    downloadProgress = (CGFloat)bytesDownloaded / (CGFloat)contentLength;

有什么方法可以使响应具有该密钥?

顺便说一句:这是我得到的回复

(gdb) po [response allHeaderFields]
{
    "Cache-Control" = "max-age=0";
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "text/plain; charset=UTF-16LE";
    Date = "Wed, 10 Aug 2011 06:21:43 GMT";
    Etag = 228n;
    Pragma = public;
    Server = dbws;
    "Transfer-Encoding" = Identity;
}

编辑(解决方法):

正如@Mitchell所说。服务器并不总是返回这样的密钥。 (奇怪的 DropBox 服务器,对于 png 是,对于 txt 文件有时不是:/) 因此,为了计算文件的 downloadProgress,我修改了(解决)源:

//In DBRequest.m 
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data {
    ...
    bytesDownloaded += [data length];
    //start of modification
    //Server might not contain @"Content-Length" key, 
    //in that case use the downloadedBytes. Is better 
    //than having an infinite value because it could
    //be handled by DBRestClient's delegate. (If not 
    //it will have the same effect as infinite)
    if ([response expectedContentLength] == NSURLResponseUnknownLength ) {
        downloadProgress = (CGFloat)bytesDownloaded;
    }else{
        NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue];
        downloadProgress = (CGFloat)bytesDownloaded / (CGFloat)contentLength; 
    }
    //end of modification
    if (downloadProgressSelector) {
        [target performSelector:downloadProgressSelector withObject:self];
    }
}

并且由于我从元数据中获得了文件的大小,所以我可以执行以下操作:

- (void)restClient:(DBRestClient *)client loadProgress:(CGFloat)progress forFile:(NSString *)destPath {
    if (progress > 1) {//Work-around: This means the progress is not a 
        progress = progress/((CGFloat)(metadataOfTheFile.totalBytes));
    }
    ... update the progress bar here
}

I wonder under what conditions an NSHTTPURLResponse object will not have key @"Content-Length" ? Is it usual/normal not to have that key?

I am trying something with the dropbox SDK and I've realized that

[[response allHeaderFields] objectForKey:@"Content-Length"]

returns nil and is causing downloadProgress to be infinite:

 NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue];
    downloadProgress = (CGFloat)bytesDownloaded / (CGFloat)contentLength;

Is there any way I can make the response have that key?

BTW: This is the response I am getting

(gdb) po [response allHeaderFields]
{
    "Cache-Control" = "max-age=0";
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "text/plain; charset=UTF-16LE";
    Date = "Wed, 10 Aug 2011 06:21:43 GMT";
    Etag = 228n;
    Pragma = public;
    Server = dbws;
    "Transfer-Encoding" = Identity;
}

EDIT (Work-arounded):

As @Mitchell said. Servers not always return such a key. (Weird DropBox servers, for png yes, for txt files sometimes no :/ )
So, in order to calculate the downloadProgress of a file I've modified (work-arounded) the source:

//In DBRequest.m 
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data {
    ...
    bytesDownloaded += [data length];
    //start of modification
    //Server might not contain @"Content-Length" key, 
    //in that case use the downloadedBytes. Is better 
    //than having an infinite value because it could
    //be handled by DBRestClient's delegate. (If not 
    //it will have the same effect as infinite)
    if ([response expectedContentLength] == NSURLResponseUnknownLength ) {
        downloadProgress = (CGFloat)bytesDownloaded;
    }else{
        NSInteger contentLength = [[[response allHeaderFields] objectForKey:@"Content-Length"] intValue];
        downloadProgress = (CGFloat)bytesDownloaded / (CGFloat)contentLength; 
    }
    //end of modification
    if (downloadProgressSelector) {
        [target performSelector:downloadProgressSelector withObject:self];
    }
}

And since I have the size of a file from the metadata I can do:

- (void)restClient:(DBRestClient *)client loadProgress:(CGFloat)progress forFile:(NSString *)destPath {
    if (progress > 1) {//Work-around: This means the progress is not a 
        progress = progress/((CGFloat)(metadataOfTheFile.totalBytes));
    }
    ... update the progress bar here
}

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

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

发布评论

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

评论(2

短叹 2024-12-05 13:20:33

如果您还记得,有时 safari 或您选择的浏览器中的下载也没有进度条,则长度不确定。在这种特殊情况下,加载旋转器是最好的展示方式。它完全取决于服务器返回的内容长度,这是可选的。

老实说,我不知道为什么它不返回该信息,也许是由于内容范围或其他一些变量决定不透露它。

您可能需要寻找其他地方才能获得该属性,但最好的建议是安全,而不是抱歉并避免所有 NaN 错误。

If you will recall that sometimes downloads in safari or your browser of choice don't have a progress bar either, the length isn't determined. In this particular case a loading spinner is the best thing to show. It entirely depends on the server returning the content-length, which is optional.

I honestly don't know why it isn't returning that info, perhaps it's due to the content-range or some other variable that it decides not to reveal it.

You may have to look elsewhere to obtain that property, but the best recommendation is to be safe, rather than sorry and avoid all NaN errors.

落花随流水 2024-12-05 13:20:33

HTTP 允许没有 Content-Length 字段,它是可选的。所以你需要处理它:

NSNumber *lengthNumber = [[response allHeaderFields] objectForKey:@"Content-Length"];
NSUInteger contentLength = [lengthNumber unsignedIntegerValue];
if (contentLength == 0) {
    // Calculate progress.
} else {
    // Can't calculate progress.
}

It's allowed for HTTP to not have a Content-Length field, it's optional. So you need to handle it:

NSNumber *lengthNumber = [[response allHeaderFields] objectForKey:@"Content-Length"];
NSUInteger contentLength = [lengthNumber unsignedIntegerValue];
if (contentLength == 0) {
    // Calculate progress.
} else {
    // Can't calculate progress.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文