AFNetworking upload data too long - ios

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.

Related

For Ios how to send image or video to server with keys in objective c

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.

How to send a key in parameter in AFMultipartFormData AFNetworking 3

This is how I"m sending the request:
NSString *string = [NSString stringWithFormat:#"%#/API/Upload",BaseURLString];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
[manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
NSError *error;
manager.responseSerializer.acceptableContentTypes = nil;
for(NSData *eachImage in self.fetchedAtt) {
NSString *mystring = #"786";
NSURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:#"POST" URLString:string parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFormData:eachImage name:#"myImage"];
[formData appendPartWithFormData:[mystring dataUsingEncoding:NSUTF8StringEncoding]
name:#"PracticeCode"];
} error:&error];
NSURLSessionDataTask *task = [manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(#"%#", error.localizedDescription);
return;
}
NSLog(#"%#", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
}];
[task resume];
}
}
Sometimes I get:
{ "Message": "Error writing MIME multipart body part to output
stream." }
//this is a 500 error
and sometimes I get
Request failed: unsupported media type (415)
You are trying to send multiple files in a single multiform request. Multipart doesn't work like this. You will have to make multiple multipart requests with 1 file at a time. So consider you have 20 files. You will create an async task that takes one file at a time, uploads it, and then performs the same function again for the next files.
And if you want to keep the references, you should return the file ids from the backend, and then append all the ids in a single array and send that array as a param in a separate api request to link the files with any object. Hope that makes sense.
Try this Afnetworking 3.0
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString: [NSString stringWithFormat:#"%#/API/Upload",BaseURLString]; parameters:#{#"text":#"name"} constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageurl]] name:#"bizcard" fileName:#"Businesscard.jpg" mimeType:#"image/jpeg"]; // you file to upload
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(#"Error: %#", [[NSString alloc]initWithData:[[error valueForKey:#"userInfo"] valueForKey:#"com.alamofire.serialization.response.error.data"] encoding:NSUTF8StringEncoding]);
callback(NO,nil);
[UtilityClass removeActivityIndicator];
} else {
callback(YES,responseObject);
}
}];
[uploadTask resume];

why the completionHandler callback is called delay then the progress(it's 1.0) in AFNetworking upload multiple images

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];

Can i keep video uploading process when my app is in background?

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

Issue while uploading Image

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.

Resources