My iOS app is crashing when my video upload is in process and app enters to background even it did not call didEnterbackground method.
Do anybody have an idea what causing it and how do I manage that uploading even if my app is in background.
Did you try background session? Like this:
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.you.uoload")
let session = NSURLSession(configuration: configuration, delegate: nil, delegateQueue: NSOperationQueue.mainQueue())
You should use NSURLSessionUploadTask to make asynchronous upload request.
Your request may be synchronous and thats why it is producing error i think.
Using AFNetworking you can do something like,
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:#"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:#"file://path/to/image.jpg"] name:#"file" fileName:#"filename.jpg" mimeType:#"image/jpeg" error:nil];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
[progressView setProgress:uploadProgress.fractionCompleted];
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"%# %#", response, responseObject);
}
}];
[uploadTask resume];
You can refer this answer for more details.
Hope this will help :)
Related
I'm using AFNetworking 3.0 and I try to send files to my server, my code work perfectly but it's very long to send the file especially when I try to send a video.
I compress the video quality and it's a little bit fast but to send a 5 sec video that take 15-20 sec.
I want to know if it's possible to improve the speed to send the file.
There is my code :
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:#"urlOfServer" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:videoData name:#"fileName" fileName:#"filename.mp4" mimeType:#"video/mp4"];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
NSLog(#"PERCENTAGE UPLOADED %f",uploadProgress.fractionCompleted);
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"%# %#", response, responseObject);
}
}];
[uploadTask resume];
Thank for your help
Since you only write to the debug console to report the progress and you don't change any UI elements, the dispatch_get_main_queue is not needed. Try to remove it and see if it makes a difference in performance.
I'm new to ios.
How to send an image or an video to php server. i have a key "Image"
for sending image and key "Video" to send video file. i need to send image or video with their keys, how can i send...?
Use Post method. And you should archive image/video to data and make sheet data to send it to server.
I suggest you use Alamofire to do this. This is the code.
let imageData = UIPNGRepresentation(image)!
Alamofire.upload(imageData, to: "https://httpbin.org/post").responseJSON { response in
debugPrint(response)
}
Here is the link.
Update
As you're familiar with OC, use AFNetworking instead. This is the code.
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:#"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:#"file://path/to/image.jpg"] name:#"file" fileName:#"filename.jpg" mimeType:#"image/jpeg" error:nil];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
[progressView setProgress:uploadProgress.fractionCompleted];
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"%# %#", response, responseObject);
}
}];
[uploadTask resume];
Here is the link.
I am using AFNetworking3.0 for upload some images in iOS, code is shown below, the images is an array of UIImage.
I have two questions:
In the progress block I print Log A when the uploadProgress.fractionCompleted is equal to 1.0, in the head of completionHandler block I print log B, then I found the time of log A and B is differs greatly. Is there some thing wrong or its normal?
When I upload multiple images, for a better performance and less upload time, should I create multiple requests or the way like below, which is the right choice?
The code looks like:
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:URL_IMAGE_SERVER parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
for(UIImage *eachImage in images) {
NSData *imageData = UIImageJPEGRepresentation(eachImage, 0.5);
[formData appendPartWithFileData:imageData name:#"upload_picture" fileName:#"filename.jpg" mimeType:#"image/jpeg"];
}
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
dispatch_async(dispatch_get_main_queue(), ^{
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
} else {
}
}];
[uploadTask resume];
I have implemented
-(void)uploadMultipleImagesUsingAFNetworkingMultipartFormat:(id)sender {
NSArray * directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[FileUtility basePath] stringByAppendingPathComponent:[self getPathOfRootImageFolderDocumentId:#"1"]] error:nil];
NSString *path = [directoryContents objectAtIndex:0];
NSString* filePath=[[[FileUtility basePath] stringByAppendingPathComponent:[self getPathOfRootImageFolderDocumentId:#"1"]] stringByAppendingPathComponent:path];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:#"com.uploadDocument.Background"];
MBProgressHUD *progres = [MBProgressHUD showHUDAddedTo:[[AppDelegate sharedInstance] window] animated:YES];
progres.mode = MBProgressHUDModeDeterminateHorizontalBar;
progres.progress = 0.0;
if (!self.sessionManager) {
_sessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config];
}
NSError *error;
NSMutableURLRequest *requet= [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:#"URLTO UPLOAD" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
NSError *error1;
[formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath] name:#"fileUpload" fileName:path mimeType:#"image/jpeg" error:&error1];
NSLog(#"%#",error1);
} error:&error];
NSURLSessionUploadTask *uploadTask = [self.sessionManager uploadTaskWithRequest:requet fromFile:[NSURL fileURLWithPath:filePath] progress:^(NSProgress * _Nonnull uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
[progres setProgress:uploadProgress.fractionCompleted];
});
NSLog(#" Progress %f",uploadProgress.fractionCompleted);
} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:[AppDelegate sharedInstance].window animated:YES];
});
}];
[uploadTask resume];
}
But when i put it in background, and set active after some time. i observe that process start from where is paused.
How to continue upload task in background too?
plz on background fetch in background modes then try :)
You just need to add below code as there is bug in NSURLSessionTask for background task.
// Prepare a temporary file to store the multipart request prior to sending it to the server due to an alleged
// bug in NSURLSessionTask.
NSString* tmpFilename = [NSString stringWithFormat:#"%f", [NSDate timeIntervalSinceReferenceDate]];
NSURL* tmpFileUrl = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:tmpFilename]];
// Dump multipart request into the temporary file.
[[AFHTTPRequestSerializer serializer] requestWithMultipartFormRequest:requet
writingStreamContentsToFile:tmpFileUrl
completionHandler:^(NSError *error)
{
// Once the multipart form is serialized into a temporary file, we can initialize
// the actual HTTP request using session manager.
// Here note that we are submitting the initial multipart request. We are, however,
// forcing the body stream to be read from the temporary file.
NSURLSessionUploadTask *uploadTask = [self.sessionManager uploadTaskWithRequest:requet fromFile:tmpFileUrl progress:^(NSProgress * _Nonnull uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
[progres setProgress:uploadProgress.fractionCompleted];
});
NSLog(#" Progress %f",uploadProgress.fractionCompleted);
} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:[AppDelegate sharedInstance].window animated:YES];
});
}];
[uploadTask resume];
}];
Hope this will help you. And if you have any question then please ask.
Step 1: here I am creating the Request
NSMutableURLRequest *request1 = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST"
URLString:[NSString stringWithFormat:#"%#%#", API_MAIN_URL, IMAGE_UPLOAD]
parameters:param constructingBodyWithBlock:^(id formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:strImagePath]
name:#"sendimage"
fileName:[strImagePath lastPathComponent]
mimeType:#"image/png"
error:nil];
} error:nil];
[request1 setValue:authToken forHTTPHeaderField:#"Authorization"];
Step 2: here I am creating the Stream at given Location
[[AFHTTPRequestSerializer serializer] requestWithMultipartFormRequest:request1
writingStreamContentsToFile:[NSURL fileURLWithPath:[strImagePath stringByDeletingPathExtension]]
completionHandler:^(NSError *error){
Step 3: here I am creating uploading task.
///here is file
NSProgress *progress = nil;
NSURLSessionUploadTask *uploadTask = [self.manager uploadTaskWithRequest:request1
fromFile:[NSURL fileURLWithPath:strImagePath]
progress:&progress
completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
NSLog(#"response : %#\n\n responseObject : %#\n\n error : %#", response, responseObject, error);
}];
[uploadTask resume];
}
}];
}
My problem is before application going to background mode I want to write all the request HTTPBody(HTTPStream) at given location with using Step:1 and Step:2 and save all the request into the NSArray after writing all the HTTPStream in File(in application Foreground) mean while I'll show Image prepare to upload.
then I'll start creating background task with the help of Step3: with passing request into this which request I have stored into the NSArray.
with this approach I am not able to upload images.
But If I call all the steps together one by one then it will upload the image on the server, but with this approach my application should be in Foreground for create request because we need to write the HTTPBody at give location.
Please help me to come out this problem I am stuck on this from last 2 week.
My application needed more then 500 images uploading over the server.
try like this
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:#"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:#"file://path/to/image.jpg"] name:#"file" fileName:#"filename.jpg" mimeType:#"image/jpeg" error:nil];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSProgress *progress = nil;
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"%# %#", response, responseObject);
}
}];
[uploadTask resume];
I have done with this task, create all the upload task without resume them and save every task within the NSArray after creation.
Once all the task are created then call a method in which we resume all the tasks.