I would like to determine the size of the data received by the URLSession in advance.

Asked 2 years ago, Updated 2 years ago, 112 views

Request to HTTPServer via iOS+URLSession and
Continue receiving response data if it is less than the preset size,
I would like to create a program to end the process if it is exceeded.

As a method, refer to Contents-length when the receive header is removed and
I thought of a way to determine whether or not this value is necessary to continue the receive process.

As for the timing of header reception, I thought of using urlSessionDataDelegate's urlSession, but
In the first place, URLSessionDataDelegate urlSession is not called.
I think it's okay to use Delete because TaskDelegate has the right timing to redirect.

·Bad use
·You can achieve your goal in a different way
Please let me know if you have any.

class httpAccess2:NSObject{
    private var queue = OperationQueue()
    private var session —URLSession?
    /// initialization process
    override init() {
        super.init()
    }

    func perform()->Bool{

        // Create URL class (setting OPT_URL/OPT_USERPWD)
        guard let url = URLComponents (string: "http://192.168.10.6:8000/test002.html") ?.url else {return false}

        // Create a URLRequest Class
        let urlRequest = URLRequest(url:url)

        // Get default settings
        let config = URLSessionConfiguration.default
        // Create Session
        self.session = URLSession(configuration:config, delete:self, deleteQueue:queue)

        // Define tasks and callback (closure) after completion
        let task = session !.dataTask(with:urlRequest) {(data, response, error) in
                print(response!)
        }
        task.resume()

        return true
    }
}

extension httpAccess2:URLSessionDataDelegate{
    funcurlSession(_session:URLSession, dataTask:URLSessionDataTask, didReceive response:URLResponse, completionHandler:@escaping(URLSession.ResponseDisposition)->Void){
        print("[URLSessionDataDelegate] didReceive response";
        print(response)
        print(" nn")
    }
}
extension httpAccess2:URLSessionTaskDelegate{

    funcurlSession(_session:URLSession, task:URLSessionTask, didFinishCollecting metrics:URLSessionTaskMetrics){
        print("[URLSessionTaskDelegate] didFinishCollecting metrics");
        print(metrics)
        print(" nn")
    }
}

swift ios nsurlsession

2022-09-30 19:40

1 Answers

If you want the URLSessionDataDelegate method to be called, you must not use dataTask (with:completionHandler:) with a completion handler.

dataTask (with:completionHandler:)

By using the completion handler, the task bypass calls to delete methods for response and data delivery

In addition, urlSession(_:dataTask:didReceive:) and urlSession(_:task:didCompleteWithError:) must be implemented correctly to retrieve incoming data without completion handler.

Furthermore, the implementation of urlSession(_:dataTask:didReceive:completionHandler:) must always call the completionHandler at the end of the process.

So this is what the implementation of URLSessionDataDelegate looks like.

extension HttpAccess2:URLSessionDataDelegate{

    funcurlSession(_session:URLSession, dataTask:URLSessionDataTask, didReceive response:URLResponse, completionHandler:@escaping(URLSession.ResponseDisposition)->Void){
        print("[URLSessionDataDelegate] didReceive response";
        print(response)
        print()
        let unknownLength: Int64 = - 1 // < - Self-defined because the constant macro `NSURLResponse UnknownLength` for ObjC cannot be used
        if response.expectedContentLength!=unknownLength
        &response.expectedContentLength>MAX_CONTENT_LENGTH{
            completionHandler (.cancel)//<- If you want to stop receiving, `.cancel`
        } else{
            completionHandler(.allow)//<- If you want to continue receiving `.allow`
        }
    }

    funcurlSession(_session:URLSession, dataTask:URLSessionDataTask, DidReceive data:Data){
        print(#function,data.count)
        // I need to build up my own data as it will be sent in small portions.
    }

    funcurlSession(_session:URLSession, task:URLSessionTask, didCompleteWithError:Error?){
        print(#function)
        iflet error = error {
            print(error)
            return
        }
        // Use the data you accumulated after completion
    }
}

(Swift modified the class name because there is a very well-kept rule that says "Type names start with capital letters".If you cannot change the class name, please read it again.)

The dataTask creation part looks like this without using the completion handler.

//Define Task
        let task=session!.dataTask(with:urlRequest)
        task.resume()

Note that HTTP is characterized by the fact that the Content-Length field of the response is not always configured, so you should also take action in that case.


2022-09-30 19:40

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.