【问题标题】:NSURLErrorDomain: Cannot decode raw dataNSURLErrorDomain:无法解码原始数据
【发布时间】:2012-07-12 13:45:54
【问题描述】:

我正在使用自己的下载管理器下载一些文件。它运行了将近半年(甚至在将其发布到 App Store 之后)
但是昨天我得到了一些有趣的东西:

Error Domain=NSURLErrorDomain Code=-1015 "cannot decode raw data"
UserInfo=0x4c12e0
{
    NSErrorFailingURLStringKey=http://***/file.json.gz,
    NSErrorFailingURLKey=http://***/file.json.gz,
    NSLocalizedDescription=cannot decode raw data
    NSUnderlyingError=0x4dcec0 "cannot decode raw data"
}

一点背景知识:我有一个 Web 服务器,它为我提供 JSON 和 gzip 压缩的 JSON。

因此,当我尝试下载 gzip 压缩文件并且仅在 iPod Touch 4G (5.1.1) 上时,问题就出现了!

发生了什么?我该如何处理?是网络服务器的问题吗?

【问题讨论】:

    标签: objective-c ios ios5 nsurlconnection ipod-touch


    【解决方案1】:

    接下来是问题。
    当 iPhone 接收到 gzip 压缩的数据时,它会自动将其解压缩。在这种情况下,Content-Length 等于 -1。因此,如果您想继续下载 gzip 压缩数据,则制作 Range 标头不是一个好主意:您不知道 gzip 压缩数据的大小。
    在我们的例子中,我们使Range 的开始等于已经下载的数据,并且在某些情况下它超过了压缩数据的大小(我什至没有说这是错误的,文件已损坏!) .所以 Web 服务器返回了 416 Requested Range not satisfiable,这就是为什么 NSURLConnection 委托的 didFailWithError 方法被调用时出现 NSURLErrorCannotDecodeRawData 错误。

    详细解释和我们的解决方案

    在下载管理器中我们有代码

    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
    [req setRange:NSMakeRange(progress, NSNotFound)];
    

    其中progress 是下载的数据量。它存储在数据库中以允许暂停和继续下载单个文件(例如,应用程序重新启动之间的大文件)。当我们想继续时,我们将Range 标头设置为 [progress; ∞) 间隔(从我们已经下载的偏移量接收数据)。

    服务器(Apache、nginx 等)即时将 gzip 编码应用于流。这有利于减小输出文件的大小,但结果是您不知道整个 gzip 文件的大小。所以它基本上意味着你不能暂停并继续下载 gzipped 流。此外,下载的 gzip 压缩块正在接收时解压缩(NSURLConnection 委托方法 connection:didReceiveData:),因此您不会知道通过了多少 gzip 压缩数据。因此,您不会创建正确的偏移量,并且服务器将从您不想要的偏移量返回数据,并且您的结果文件首先将被损坏,其次,一旦您超过内容长度并收到416

    因此,没有一个浏览器或其他任何东西会允许您继续下载动态(根据请求生成)或 gzip 压缩的内容。如果您想暂停和继续大型压缩文件(在我们的示例中为 20 Mb JSON),请将它们设为静态并存档,或者继续 gzip 压缩它们并希望用户等到文件下载完成。

    所以我们选择了第二条路径,现在如果 Content-Lenght 未知 (-1),则不要设置范围。

    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
    
    if (urlResponse.expectedContentLength != NSURLResponseUnknownLength) {
        [req setRange:NSMakeRange(progress, NSNotFound)];
    }
    

    【讨论】:

    • 你是如何解决这个问题的?
    • @Ard 我已经用我们的解决方案更新了这篇文章。
    • 非常感谢您的解释,我面临的问题是我从服务器获取 Content-Length 但当“content-encoding: gzip”为放。我在这里更详细地解释了我的情况:stackoverflow.com/questions/23692906/…
    • iOS 会尝试自动解压缩它,就像 Safari 一样...这是我没想到会发生的事情...我听到了...谢谢伙计!
    猜你喜欢
    • 2015-11-17
    • 2018-12-14
    • 2012-07-04
    • 2015-07-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    相关资源
    最近更新 更多