Post Image Using multiPart To URL - ios

Actually i have json parameter
[dictionary setObject:_dateOfBirth.text forKey:#"birth_date"];
[dictionary setObject:_tfCountry.text forKey:#"country"];
[dictionary setObject:_tfEmail.text forKey:#"email"];
[dictionary setObject:#"" forKey:#"fromLogin"];
[dictionary setObject:#1 forKey:#"gender"];
[dictionary setObject:#"signup" forKey:#"methodName"];
[dictionary setObject:_tfContact.text forKey:#"mobile"];
[dictionary setObject:_tfName.text forKey:#"name"];
[dictionary setObject:_tfNickName.text forKey:#"nickname"];
[dictionary setObject:_tfPassword.text forKey:#"password"];
[dictionary setObject:_tfPinCode.text forKey:#"pincode"];
There Is also a Image that i have to set profile_pic as a Key.
Now I have Converted all Parameter as a data and POst That Data lie This
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:kNilOptions error:nil];
// this is your service request url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://proteen2.inexture.com/webservice"]];
// set the content as format
[request setHTTPMethod:#"POST"];
[request setHTTPBody: jsonData];
// this is your response type
[request setValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"content-type"];
NSError *err;
NSURLResponse *response;
// send the synchronous connection
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
// here add your server response NSJSONSerialization
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:responseData options: NSJSONReadingMutableContainers error: &err];
It's Works fine for Text, Now how to attach Image to that Parameter, I am only aware with Multi Part but not getting that Point. Please Help

You need to manage many thing here, like set boundry append image data etc etc.
You should use AFNetworking to make is very simple. Download from github and just drag and drop library to your project and import AFNetworking.h in your class and then you can do something like,
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer]multipartFormRequestWithMethod:#"POST" URLString:#"urlstring" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
//Append image here for example;
UIImage *img = tempImageView.image;
NSData *imgData = UIImageJPEGRepresentation(img, 0.5);
[formData appendPartWithFileData:imgData name:#"imagename/serversideparameter" fileName:#"imagename" mimeType:#"image/jpeg"];
} error:nil];
//Send this request to server. Something like,
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc]initWithSessionConfiguration:configuration];
[[manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (!error) {
NSLog(#"success!!");
NSLog(#"here is the response : %#",responseObject);
}
else{
NSLog(#"Error Occured : %#",error.localizedDescription);
}
}]resume];
You shouldn't use NSUrlConnection because it is deprecated now. It's better to use NSUrlSession which i have used in answer via AFNetworking.
If you don't want to use AFNetworking then refer this stackoverflow post. It have great explanation step by step in answer.

Related

How to add Authorization in Header for Get method in objective c

I want to add my token in Authorization header
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSLog(#"%# urlis ====>",urlString);
NSData *data = [NSData dataWithContentsOfURL:url2];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *dataaa = [ret dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:dataaa options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
You can use NSMutableRequest -
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url2];
[request setHTTPMethod:#"GET"];
[request setValue:[[NSUserDefaults standardUserDefaults] valueForKey:#"token"] forHTTPHeaderField:#"Authorization"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// add any additional headers or parameters
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
// do your response handling
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
}
}];
[downloadTask resume];
To understand in more detail about NSURLSession refer to this Tutorial
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
[request addValue:VALUE forHTTPHeaderField:#"Authorization"];
Try to create a Mutable request and add your authorization header to it. You can send this request as a parameter to any one. Either to AFNetworking (or some third party network) library API calls or to URLSession (by Apple)
For more info on NSMutableRequest
You can pass it by
[request setValue:#"Your Token" forHTTPHeaderField:#"Authorization"];
Edited :
As per your comment if you want to change your response then your should use NSMutableDictionary instead of NSArray like.
Note: Your response should Dictionary if it will array then use NSMutableArray
NSMutableDictionary * resultDict =[json objectForKey:#"name"];
[resultDict setObject:#"Your Token" forKey:#"Authorization"];

POST base 64 image string to a server on iOS

To my understanding, to use this website I have to convert an image to a base64 encoded image and then send it to this website. The website will then send me back a number (as a decimal).
https://docs.indico.io/docs/rest-api-image-analysis
I've tried using a number of steps, namely trying to alter a similar process used for sending text and receiving a number. Any tips?
UPDATE:
- (IBAction)press:(id)sender {
//UIImage *imager = photos.image;
NSData *imageData = UIImageJPEGRepresentation(photos.image, 1.0);
NSString *base64Img = [imageData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
//not sure if #"data" or #"data.json" and whether the base64img should be behind it
NSDictionary *parameters = #{#"data":base64Img};
NSMutableString *parameterString = [NSMutableString string];
for (NSString *key in [parameters allKeys]) {
if ([parameterString length]) {
[parameterString appendString:#"&"];
}
[parameterString appendFormat:#"%#=%#", key, parameters[key]];
NSURL *url = [NSURL URLWithString:#"http://apiv2.indico.io/contentfiltering?key='17767cb46eb4b4f568832be2c953022b"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[parameterString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
if ([data length]) {
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//GET RESULT;
NSLog(#"A %#", parameters[#"results"]);
}
} else {
NSLog(#"%#", error);
}
}];
[task resume];
}
the results I get usually return as (null)
maybe try going
NSDictionary *parameters = #{#"data":base64Img};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters
options:nil
error:&error];
//do some error checking
NSURL *url = [NSURL URLWithString:#"http://apiv2.indico.io/contentfiltering?key='17767cb46eb4b4f568832be2c953022b"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:jsonData];
//...
just doing this off the top of my head so may need some tweaking
If I had to guess it looks like you've accidentally added a typo to your API key. In the line above:
http://apiv2.indico.io/contentfiltering?key='17767cb46eb4b4f568832be2c953022b
should instead read:
http://apiv2.indico.io/contentfiltering?key=17767cb46eb4b4f568832be2c953022b
Since URL parameters are sometimes quoted and I'm not extremely familiar with objective-c's internal request handling I would guess that that is leading to the strange behavior you're seeing.

Send UIImage POST to server from UIImagePickerController?

I am trying to send a UIImage take with the UIImagePickerController to a server POST along with other pertinent values. But I get at the line that tries to set the dictionary value #"image" to UIImageJPEGRepresentation(image, 1.0):
-(void)sendImageToServer:(UIImage *)image
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 4;
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:nil delegateQueue:queue];
NSURL *uploadURL = [NSURL URLWithString:#"http://...."];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:uploadURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
[request addValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPMethod:#"POST"];
NSData *postData = [[NSData alloc] init];
[postData setValue:UIImageJPEGRepresentation(image, 1.0) forKey:#"image"];
[postData setValue:#"1" forKey:#"categories[0]"];
[postData setValue:#"4" forKey:#"categories[1]"];
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
fromData:postData
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
NSError *err;
NSDictionary *JSONDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&err];
NSLog(#"HTTP 200 response: %#", JSONDict);
});
} else {
NSLog(#"HTTP %ld status!", (long)httpResponse.statusCode);
}
} else {
NSLog(#"HTTP post image error: %#", error);
}
}];
[uploadTask resume];
}
JSON serialization does not work here, because images are not valid JSON values. If on the other hand I try:
...
NSMutableData *postData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:postData];
[archiver encodeObject:UIImageJPEGRepresentation(image, 1.0) forKey:#"image"];
[archiver encodeObject:#"1" forKey:#"categories[0]"];
[archiver encodeObject:#"4" forKey:#"categories[1]"];
[archiver finishEncoding];
//NSData *postData = [NSJSONSerialization dataWithJSONObject:dataDict options:NSJSONWritingPrettyPrinted error:&jsonError];
//Now you can post the json data
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
fromData:postData
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {...
The key:value pairs archived do not seem to get to the server as such. This must be a routinely iOS coding task.
Even if I just try:
NSError *jsonError;
NSData *postData = [NSJSONSerialization dataWithJSONObject:#{#"image":#"123",#"categories[0]":#"1",#"categories[1]":#"4"} options:NSJSONWritingPrettyPrinted error:&jsonError];
The server does not get any keys at all...
That's not the proper usage of NSData. It's crashing right now because NSData does not have key named image (..or the other two after that). What you need to do is create an NSDictionary and then convert that to NSData.
Do something like this instead:
NSDictionary *dictionary = [NSDictionary alloc]initWithObjectsAndKeys:image,#"image",#(1),#"categories[0]",#(4),#"categories[1]", nil];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary]; //Not currently using NSJSONSerialization since you want to post a Dictionary with an invalid NSJSONSerialization type in it.
//Now you can post the json data
Give a try with AFNetworking, it have a great way to make uploads, you can find the samples here: https://github.com/AFNetworking/AFNetworking#creating-an-upload-task
I personally recommend everyone to use it, since I started to use I didn't have any trouble to communicate my apps with webservers.
Use AFNetworking and the multi-part form post. Here is a rough example (note I am passing in a block so your implementation will vary):
AFHTTPRequestOperation *operation = [self POST:FullURLString parameters:Params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:fileData name:fileName fileName:fileName mimeType:mimeType];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSData *responseData = [operation responseData];
id retObj;
NSError *error = nil;
if (responseData) {
retObj = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
}
// Pass back the serialized object (either an NSArray of type NSDictionaries or an NSArray of type customClass)
block(retObj);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failed with error = [Error]: %#", error);
block(nil);
}];

Run Two urls in single method

I am finding for the way to run 2 services in a method one after another to post images one by one . after the 1st service i need to get response then i need pass that response to 2nd service.
The code i've used to post run a single service to post single image is
NSString *url=[NSString stringWithFormat:#"http://37.187.152.236/UserImage.svc/InsertObjectImage?%#",requestString];
NSLog(#"url1%#",url);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"POST"];
// Create 'POST' MutableRequest with Data and Other Image Attachment.
NSString *boundary = #"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:#"multipart/form-data; boundary=%#", boundary];
[request setValue:contentType forHTTPHeaderField:#"Content-Type"];
NSData *data = UIImageJPEGRepresentation(chosenImage1, 0.2f);
[request addValue:#"image/JPEG" forHTTPHeaderField:#"Content-Type"];
NSMutableData *body = [NSMutableData data];
[body appendData:[NSData dataWithData:data]];
[request setHTTPBody:body];
some similar questions may be there in stackoverflow but my need is completely different.
Flow of method must be like this
*Run 1st url --> generate response ({userid:"20",message:"success"} ) --> run 2nd url *
help me, thanks in advance for everyone.
you can call the second method with respect to the response of first method
-(void)webservicecall {
WebApiController *obj=[[WebApiController alloc]init];
NSMutableDictionary *imageparameter = [NSMutableDictionary dictionary];
NSData *imagedata = UIImagePNGRepresentation(self.productImageView.image);
[imageparameter setValue:imagedata forKey:#"image"];
[obj callAPIWithImage:#"upload.php" WithImageParameter:imageparameter WithoutImageParameter:nil SuccessCallback:#selector(upload_response:Response:) andDelegate:self];
}
Response From Web Service:
-(void)upload_response:(NSString *)apiAlias Response:(NSData *)response {
NSMutableDictionary *jsonDictionary=[NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableContainers error:nil];
NSString *responseMsg=[[NSString alloc] initWithString:[jsonDictionary objectForKey:#"message"]];
if ([responseCode isEqualToString:#"success"]) {
[self CallToSecondWebService];
}
}
Second WebService:
-(void)CallToSecondWebService
{
}
http://codewithchris.com/tutorial-how-to-use-ios-nsurlconnection-by-example/
NSURLConnection synchronous request on https
how to send Asynchronous URL Request?
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/NSURLConnection_Class/Reference/Reference.html
You can read from all of these as per your choice..
Maybe this will help you.
-(void)getData:(NSString *)userid
{
/*--- Your Current code here ---*/
/*--- this is synchronous request you can use asynchronous as well ---*/
NSURLResponse *response = nil;
NSData *dataResponse = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
/*--- Save your response if you want ---*/
id Obj = [NSJSONSerialization JSONObjectWithData:dataResponse options:NSJSONReadingMutableLeaves error:nil];
if ([Obj isKindOfClass:[NSArray class]])
{
/*--- here you get response ---*/
/*--- I've created sample method that you can pass userid in same method ---*/
/*--- Call same method or create new method and do same thing ---*/
[self getData:[[Obj objectAtIndex:0] valueForKey:#"userid"]];
}
}
I would strongly discourage you in using sync connections, they block the thread until they have finished and if this thread is the main thread, they will block the user interactions. Also you will not have control on the chunk sent or auth challenges.
In your case most probably the best is to use a network manger such as AFNetworking 2 and creating different network operations, after that you can add dependencies between them (thus chaining them if you like).
The other way is dispatch_group. You can add the operations (or sessions) to a group and wait until they end.
[UPDATE]
In AFnetworking 2.0
NSDictionary * parameter = #{ParameterImage : mainImage ? #"1" : #"0",};
NSError * __autoreleasing * constructingError = nil;
AFHTTPRequestOperation * op1 = [self POST:ApiImageUploadURL parameters:parameter constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:imagePath] name: ParameterImageData error:constructingError];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError * error = nil;
id objects = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error];
DLog(#"Response %#", objects);
NSString * imageID = [objects[#"id"] stringValue];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DLog(#"Error%#", error);
}];
// create operation op2
[op2 addDependecy:op1];

Is there a 'trick' for sending raw NSString rather than NSData in a NSURLSession connection?

I'm attempting to communicate with a backend using NSURLSession, however, the backend wasn't set up to properly read NSData, so it views the NSData login details I send over as false, I wanna know if its possible to get NSURLSession to send raw strings rather than NSData objects. I've looked in books and the webs and I've been stumped for weeks.
Redoing the backend is not an option, the engineer in charge of that left. Any help is welcome.
Thanks. Here's what I've done so far, in case anyone needs to see some code.
NSError *error;
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration ];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
NSString *rawUrlString = #"backend_url";
NSURL *url = [NSURL URLWithString:rawUrlString];
NSLog(#"%#", url);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:
login data here
nil];
//NSLog(#"%#", parameters);
NSData *rawJson = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:&error];
NSString *myString = [[NSString alloc] initWithData:rawJson encoding:NSUTF8StringEncoding];
NSData *finalData = [myString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *body = [NSMutableData data];
[body appendData:finalData];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:body];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"charset"];
[request setValue:#"XMLHttpRequest" forHTTPHeaderField:#"X-Requested-With"];
NSURLSessionDataTask *postTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSLog(#"%#", [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]);
}];
[postTask resume];
`
UPDATE: I've cleaned up the unnecessary bits this is the final code (still doesn't work though)
NSError *error;
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration ];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
NSString *rawUrlString = #"backend_url";
NSURL *url = [NSURL URLWithString:rawUrlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:login details nil];
NSData *rawJson = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:&error];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:rawJson];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLSessionDataTask *postTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSLog(#"%#", [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]);
}];
[postTask resume];
Your backend is setup to handle NSData. It's impossible to send a string over an internet connection, you can only send NSData and all servers expect it.
This code here is wrong:
NSData *rawJson = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:&error];
NSString *myString = [[NSString alloc] initWithData:rawJson encoding:NSUTF8StringEncoding];
NSData *finalData = [myString dataUsingEncoding:NSUTF8StringEncoding];
Instead just do this:
NSData *finalData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:&error];
The NSData object will contain a string in the correct format for the server to also recognise as a string. Note it will be in UTF-8 encoding, perhaps on some servers you will want to change that to something else.

Resources