ios 目标 c:如何让 NSURLSession 从服务器返回 Content-Length(http 标头)

Posted

技术标签:

【中文标题】ios 目标 c:如何让 NSURLSession 从服务器返回 Content-Length(http 标头)【英文标题】:ios objective c : How to get NSURLSession to return Content-Length(http header) from server 【发布时间】:2016-12-02 06:46:59 【问题描述】:

我已经尝试过了How to get NSURLSession to return Content-Length(http header) from server. Objective-c, ios

- (long long) getContentLength

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
    request.HTTPMethod = @"HEAD";
    [request addValue:@"identity" forHTTPHeaderField:@"Accept-Encoding"];

    NSURLSessionDownloadTask *uploadTask
    = [session downloadTaskWithRequest:request
                     completionHandler:^(NSURL *url,NSURLResponse *response,NSError *error) 
                         NSLog(@"handler size: %lld", response.expectedContentLength);
                       totalContentFileLength = [[NSNumber alloc] initWithFloat:response.expectedContentLength].longLongValue;

                     ];
    NSLog(@"content length=%lld", totalContentFileLength);
    [uploadTask resume];
    return totalContentFileLength;

我总是从返回值中得到0

【问题讨论】:

【参考方案1】:

对于 Swift 3.0: (使用普通的老式函数..)

func getContentLengthOf(urlString: String,
                        completionHandler: @escaping (Int64?) -> ()  ) 

    let url = URL(string: urlString)
    var request = URLRequest(url: url!)
    request.httpMethod = "HEAD"
    request.addValue( "identity", forHTTPHeaderField: "Accept-Encoding")

    let session = URLSession(configuration: URLSessionConfiguration.default)

    let task = session.dataTask(with: request, completionHandler: (data, response, error) -> Void in
        if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode 
            let contentLength : Int64 = response.expectedContentLength
            completionHandler(contentLength)

         else 
            completionHandler(nil)
        
    )

    task.resume()

然后这样调用:

....
        let URLString = "https://lh4.googleusercontent.com/-KdgJnz1HIdQ/AAAAAAAAAAI/AAAAAAAAA8s/31PBnNCL-qs/s0-c-k-no-ns/photo.jpg"

        getContentLengthOf(urlString: URLString)  (contentLength: Int64?) in
            if let contentLength = contentLength 
                print("size is: \(contentLength)")
            else
                print("error getting contentLength")
            
        

在回调中你会得到一个可选的 Int64。

【讨论】:

【参考方案2】:

这是因为你在completion handler之外返回函数的值,所以你的函数在得到服务器响应之前就返回了值。现在你不能从completion handler 返回值。因此,您需要创建具有自定义 completion handler 作为参数的方法,例如,

 - (void) getContentLength : (void(^)(long long returnValue))completionHandler
 


NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
request.HTTPMethod = @"HEAD";
[request addValue:@"identity" forHTTPHeaderField:@"Accept-Encoding"];

NSURLSessionDownloadTask *uploadTask
= [session downloadTaskWithRequest:request
                 completionHandler:^(NSURL *url,NSURLResponse *response,NSError *error) 

                     NSLog(@"handler size: %lld", response.expectedContentLength);
                     totalContentFileLength = [[NSNumber alloc] initWithFloat:response.expectedContentLength].longLongValue;

                     completionHandler(totalContentFileLength);

                 ];
NSLog(@"content length=%lld", totalContentFileLength);
[uploadTask resume];


你可以像这样调用这个方法,

   [self getContentLength:^(long long returnValue) 

    NSLog(@"your content length : %lld",returnValue);

];

【讨论】:

以上是关于ios 目标 c:如何让 NSURLSession 从服务器返回 Content-Length(http 标头)的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7系列译文:忘记NSURLConnection,拥抱NSURLSession吧!

iOS:如何增加 NSURLSession 上传任务的块大小?

iOS NSURLSession 使用自定义委托处理数据任务的完成

NSURLSession 下载任务 - Xamarin iOS F#

ios8:如何使用 NSURLSession 在后台上传 100 张照片?可用空间问题

如何使用 iOS 7 的 NSURLSession 接受自签名 SSL 证书