我正在尝试使用此后续委托方法计算进度条dataTaskWithURL中接收的数据:NSURLSessionTaskDelegate, NSURLSessionDataDelegate,这是我在视图didload中使用的代码,我未使用请求。
网络地址:http://www.roimulia.com/db.php
全局属性:

var dataTodownload : NSMutableData!
var downloadSize : Float!

ViewDidload:
var defaultConfigObject : NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
var  defaultSession  : NSURLSession = NSURLSession(configuration: defaultConfigObject, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let url = NSURL(string: "http://www.roimulia.com/db.php")
var datatask = defaultSession.dataTaskWithURL(url!)
datatask.resume()

相关委托方法:
   func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void)
    {
        completionHandler(NSURLSessionResponseDisposition.Allow)
        prgs_bar.progress = 0
        downloadSize = Float(response.expectedContentLength)
        dataTodownload = NSMutableData()
    }

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData)
    {
        dataTodownload.appendData(data)
        prgs_bar.progress = Float(dataTodownload.length) / Float(downloadSize)
    }

调试后,我发现进度条不会加载,即使数据已完全接收到也是如此。发生这种情况的原因是因为response.expectedContentLength的值等于-1,这意味着压缩服务器上的文件时长度的默认值。

=============================

由ROB ANSWER更新:

=============================

因此,起初,请忘记我在下面的评论,我想念您写的东西。
罗布提出了3个答案。如我所见,答案编号 2 是我正在寻找的答案,因为它使用委托方法,并且因为我打算使用此应用,所以我需要使其尽可能高效(除非和我错了,也请参考这行,我真的很在乎从网络上下载/接收数据的效率()。
所以我发现了2件有趣的事情:
1)当我在请求在我的服务器上定位并解析为json的请求中使用文件作为url时-就像 http://roimulia.com/db.php 一样,它的确通过didCompleteWithError委托方法接收了数据,并且我可以使用NSJSONSerialization.JSONObjectWithData来获取数据。 expectedContentLength等于-1,所以我无法计算进度。
但是,当我将此链接用于示例时(而不是在我的服务器上定位) http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo -完美加载),expectedContentLength不是eqal -1,我可以计算进度。
所以结论一:1)问题可能与我的服务器有关,或者与我在php文件中回显Array的方式有关(尽管我可以在最后使用数据,所以很奇怪)。
,让我知道您对的看法)
2)如果我们无法通过解决方案编号2 解决它:

1)与解决方案2相比,其他两个解决方案(1,3)的效率(在下载速度,进度等方面)效率低多少?如果有的话?

我希望它现在足够详细:X我等不及要解决它

最佳答案

正确。如果内容已压缩,则没有预期的长度。

  • 您可以通过将Accept-Encoding标头设置为identity来关闭压缩:
    let url = NSURL(string: "http://www.roimulia.com/db.php")
    let request = NSMutableURLRequest(URL: url!)
    request.setValue("identity", forHTTPHeaderField: "Accept-Encoding")
    
    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
    
    let task = session.dataTaskWithRequest(request)
    task.resume()
    

    应该注意的是,即使那样,您也可能无法获得有效的expectedContentLength(例如,不确定长度的分块响应),但通常它会起作用。
  • 另外,您可能想要显示随接收到的数据而移动的内容,而不是为了显示进度视图而减慢下载的速度,让用户知道有实际的数据在接收,但是让它循环:
    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
        dataTodownload.appendData(data)
    
        var progress: Float!
    
        if downloadSize < 0 {
            progress = (Float(dataTodownload.length) % 10_000_000.0) / 10_000_000.0
        } else {
            progress = Float(dataTodownload.length) / downloadSize
        }
    
        progressView.progress = progress
    }
    
  • 由于您有一个PHP Web服务来提供此下载,因此从理论上讲,您可以让服务器确定下载的未压缩大小,然后以某种方式将其包括在响应中(自定义标头,返回该请求的其他API调用,等等。)。
  • 10-08 15:21