【问题标题】:iOS get file size before downloadingiOS在下载前获取文件大小
【发布时间】:2015-07-31 00:47:21
【问题描述】:

我找不到适合我的解决方案。但是我需要获取我正在下载的视频的文件大小,以便我可以确保用户在他的手机上有足够的空间来下载它。

我的想法是检查视频的大小,如果用户有空间,我会下载它。有什么建议吗?

NSURL *url = [NSURL URLWithString:stringURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];

NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {...}];

【问题讨论】:

标签: ios download size nsurlsession nsurlsessiondownloadtask


【解决方案1】:

这是其他答案的变体,它使用函数(在 Swift 4 中)在检索大小时调用闭包:

func getDownloadSize(url: URL, completion: @escaping (Int64, Error?) -> Void) {
    let timeoutInterval = 5.0
    var request = URLRequest(url: url,
                             cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
                             timeoutInterval: timeoutInterval)
    request.httpMethod = "HEAD"
    URLSession.shared.dataTask(with: request) { (data, response, error) in
        let contentLength = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
        completion(contentLength, error)
    }.resume()
}

这个函数的使用方法如下:

let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png")!
getDownloadSize(url: url, completion: { (size, error) in
    if error != nil {
        print("An error occurred when retrieving the download size: \(error.localizedDescription)")
    } else {
        print("The download size is \(size).")
    }
})

【讨论】:

    【解决方案2】:

    斯威夫特 3: 由于您正在调用 dataTask ,因此您不能在块之外使用该值,因此请以这种方式使用它。

     var contentLength: Int64 = NSURLSessionTransferSizeUnknown
                    let request = NSMutableURLRequest(url: url as URL, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0);
                    request.httpMethod = "HEAD";
                    request.timeoutInterval = 5;
                    let group = DispatchGroup()
                    group.enter()
                    URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
                        contentLength = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
    //Here you should use the value
                        print("contentLength",contentLength)
                        group.leave()
                    }).resume()
    

    【讨论】:

      【解决方案3】:

      使用此函数获取 URL 的远程大小。请注意这个函数是同步的并且会阻塞线程,所以从不同于主线程的线程中调用它:

      extension NSURL {
          var remoteSize: Int64 {
              var contentLength: Int64 = NSURLSessionTransferSizeUnknown
              let request = NSMutableURLRequest(URL: self, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0);
              request.HTTPMethod = "HEAD";
              request.timeoutInterval = 5;
              let group = dispatch_group_create()
              dispatch_group_enter(group)
              NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
                  contentLength = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
                  dispatch_group_leave(group)
              }).resume()
              dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, Int64(5 * NSEC_PER_SEC)))
              return contentLength
          }
      }
      

      然后在与主线程不同的线程上随处调用 remoteSize 变量:

      let size = url.remoteSize
      

      【讨论】:

      • @RayKing 增加超时时间,现在是 5 秒,你可以根据需要增加它
      • 这样吗? DispatchQueue.main.asyncAfter(deadline: .now() + 15) { print(NSURL(fileURLWithPath: track.url!).remoteSize) } 仍然得到 - 1
      • @RayKing 在 dispatch_group_wait 中更改 5。我注意到在 swift 3 版本中,作者省略了这一行,导致该代码无法使用
      【解决方案4】:

      SWIFT 3:

      extension NSURL {
          var remoteSize: Int64 {
              var contentLength: Int64 = NSURLSessionTransferSizeUnknown
              let request = NSMutableURLRequest(url: self as URL, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30.0);
              request.httpMethod = "HEAD";
              request.timeoutInterval = 5;
              let group = DispatchGroup()
              group.enter()
              URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
                  contentLength = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
                  group.leave()
              }).resume()
      
              return contentLength
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2013-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-14
        • 2010-09-05
        • 2013-05-22
        相关资源
        最近更新 更多