NickProvost
NickProvost

Reputation: 367

iOS get file size before downloading

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) {...}];

Upvotes: 0

Views: 5996

Answers (4)

Alan Kinnaman
Alan Kinnaman

Reputation: 926

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).")
    }
})

Upvotes: 10

Jad
Jad

Reputation: 2238

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

Upvotes: 0

Yaroslav Dukal
Yaroslav Dukal

Reputation: 3942

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

Upvotes: -1

Mousavian
Mousavian

Reputation: 1485

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

Upvotes: -1

Related Questions