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:
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
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.