iosalamofirensurlsessionnsurlsessionconfiguration

MultipartFormData upload using Alamofire


I have been trying to implement a multipart form data using Alamofire. I made some code and it works great for requests that performs under 60 seconds. However, if the request takes more than that, it ends and the upload does not finish:

Variables view

Also, I am getting this output (probably means that my app is trying to write to a closed tcp socket):

2017-06-20 17:22:21.924948 app[4645:1381848] [] nw_endpoint_flow_prepare_output_frames [110.1 10.39.80.102:8550 ready socket-flow (satisfied)] Failed to use 1 frames, marking as failed

2017-06-20 17:22:21.928262 app[4645:1381848] [] nw_endpoint_handler_add_write_request [110.1 10.39.80.102:8550 failed socket-flow (satisfied)] cannot accept write requests

2017-06-20 17:22:21.929278 app[4645:1381027] [] __tcp_connection_write_eof_block_invoke Write close callback received error: [22] Invalid argument

I have already tried to modify the URLSessionConfiguration that I am using to perform the request by changing the timeoutIntervalForRequest and timeoutIntervalForResource parameters:

func initManager(timeoutInterval:Double) {
    
    let configuration = URLSessionConfiguration.default
    
    configuration.timeoutIntervalForRequest = timeoutInterval
    configuration.timeoutIntervalForResource = timeoutInterval
    
    alamofireManager = Alamofire.SessionManager(configuration: configuration)
}

However, I still get the same problem. Does anyone know how to solve this? Or does anyone face the same problem?

Thanks


Solution

  • You might be hitting an execution time limit on the server side. That said, I think there's also a bug in iOS 10.0 – 10.2.x that can cause this misbehavior. (More at https://forums.developer.apple.com/thread/67606.)

    Even if you fix the cause of this particular problem, though, the fundamental problem here is a design problem, not a problem with a request, per se. Networks are unreliable, and cellular networks doubly so. The odds of maintaining a cellular connection for more than a minute are roughly the same as the odds of winning the lottery. (Yes, that's hyperbole, but you get the idea.)

    I would suggest the following alternative approach:

    Then, on the client side, you start uploading. If the upload fails for any reason, you issue a GET on the file size endpoint, and issue a new POST with the offset set to the first byte after the file's length (and providing only the last part of the upload data, obviously).

    This avoids losing a single byte of the upload whether the connection failed because of a bug in iOS, a server misconfiguration, or just a random network glitch. Even better, it is likely to work acceptably with background uploading in NSURLSession as well.