Hi,
The problem I am seeing occurs only for large file uploads (300-500 MBs). What I am observing is that iOS sometimes does NOT call didCompleteWithError even after my server sends a response. In the client logs I can see that the didSendBodyData method gets called several times. Which is expected, however it does not seem to stop even after sending all the bytes. I have also noticed that sometimes the taskId changes or the totalBytesSent gets reset. Which does not make any sense since I have not queued up another upload task. I only called resume once.
Also note: This behavior happens when the app is in the foreground. I have not attempted testing background uploads yet. Additionally I have tired using the default session and still observe the same behavior.
Everything works as expected the file is small.(~50 Mbs). The didRecieveData method gets called along with the didCompleteWithError method.
Below are some code snippets of the background task:
//FileOperationsDelegate.mm
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
NSNumber* taskId = [NSNumber numberWithUnsignedInteger:task.taskIdentifier];
AwLog(@"DidSendBodyData for taskID: %@ BytesSent: %lld TotalBytesSent: %lld ExpectedToSend: %lld\n", taskId, bytesSent, totalBytesSent, totalBytesExpectedToSend);
if (updateFileProgressCallback != NULL)
{
updateFileProgressCallback(bytesSent, totalBytesSent);
}
}
Here is by backgroundSession.
//FileOperationsDelegate.mm
- (NSURLSession *)backgroundSession
{
static NSURLSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: KEY_BACKGROUND_SESSSION_ID];
configuration.discretionary = YES;
configuration.sessionSendsLaunchEvents = YES;
configuration.URLCache = nil;
bool wifiOnly = [ClientConfiguration.sharedInstance isWifiOnlyEnabled];
if (wifiOnly)
{
configuration.allowsCellularAccess = false;
}
NSOperationQueue* delegateMainQueue = [NSOperationQueue mainQueue];
delegateMainQueue.maxConcurrentOperationCount = 1;
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue: delegateMainQueue];
});
return session;
}
Creating the upload task
//FileUploader.mm
NSURLSession* backgroundSession = [FileOperationsSessionDelegate.sharedInstance backgroundSession];
NSMutableString *file = [[NSMutableString alloc] initWithString:absLocalPath];
[file insertString:@"file://" atIndex:0];
NSURL* fileToBeUploaded = [NSURL URLWithString:file];
NSURLSessionUploadTask* uploadTask = [backgroundSession uploadTaskWithRequest:urlRequest fromFile:fileToBeUploaded];
uploadTask.countOfBytesClientExpectsToSend = self.uploadSizeBytes;
uploadTask.countOfBytesClientExpectsToReceive = 450;
ConnectionCallback uploadCompleteCallback = ^(NSURLResponse * response, NSData * data, NSError * error) {
// A callback to complete the file upload. It will update the UI and notify the user
// on how the upload went.
}
BytesUploadedCallback updateFileProgressCallback = ^(long bytesWritten, long totalBytesWritten)
// A callback that will update the progress bar.
};
[FileOperationsSessionDelegate.sharedInstance setUploadCallback:uploadCompleteCallback];
[FileOperationsSessionDelegate.sharedInstance setConnectionCallback:updateFileProgressCallback];;
[uploadTask resume];
Any help with this will be greatly apperiated.
Thanks : )
Specs:
iOS version 12.3
Device: iPad Pro 11
Xcode: 10.1