0

I couldn't find a solution that worked for me. But I need to get the file size of a video I am downloading so that I can make sure the user has enough space on his phone for it.

My thoughts are to check the size of the video, then if the user has space for it, I would download it. Any recommendations?

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) {...}];
NickProvost
  • 367
  • 5
  • 22

4 Answers4

10

Here's a variation of the other answers that uses a function (in Swift 4) to call a closure when the size is retrieved:

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()
}

Here's how this function could be used:

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).")
    }
})
Alan Kinnaman
  • 877
  • 12
  • 20
0

Swift 3: Since you are calling dataTask you can't use the value outside of the block so use it this way.

 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()
Jad
  • 2,139
  • 1
  • 16
  • 28
-1

Use this function to get remote size of URL. Please note this function is synchronous and will block thread, so call it from a thread different from main thread:

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
    }
}

then call remoteSize variable everywhere you need, on a thread different from main thread:

let size = url.remoteSize
Mousavian
  • 1,435
  • 1
  • 15
  • 23
  • @RayKing increase timeout, it's 5 second now, you can increase it as much as you need – Mousavian Oct 05 '16 at 19:45
  • like this? DispatchQueue.main.asyncAfter(deadline: .now() + 15) { print(NSURL(fileURLWithPath: track.url!).remoteSize) } With this still getting - 1 – Yaroslav Dukal Oct 05 '16 at 19:50
  • @RayKing change 5 in dispatch_group_wait. I noticed in swift 3 version author omited this line which renders that code unusable – Mousavian Oct 05 '16 at 21:25
-1

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
    }
}
Yaroslav Dukal
  • 3,894
  • 29
  • 36