Passing NSData to web service along with NSDictionary Parameter - ios

I have all the AFNetworking Services written in Separate web service classe. upto now i have been doing it fine passing NSDictionary parameters. but now i got a problem when i need to pass NSData file to web service.
Here how im performing web service
NSData *imageData = UIImageJPEGRepresentation(self.profileImg.image, 0.5); // I need to pass this imageData
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSString *stringFromDate = [dateFormatter stringFromDate:[NSDate date]];
//Encrypting Password
NSString *passwordString = _password.text;
NSString *passwordMD5 = [passwordString MD5String];
NSDictionary *params = #{#"username": _username.text,
#"password": passwordMD5,
#"email": _email.text,
#"date":stringFromDate};
WebService *serviceObj = [[WebService alloc] init];
serviceObj.delegate = self;
[serviceObj performSelectorInBackground:#selector(doRegister:) withObject:params];
Here how i have written web service
NSMutableDictionary * parameters = [[NSMutableDictionary alloc]initWithDictionary:params];
NSURL *baseURL = [NSURL URLWithString:#"http://www.example.com/register.php"];
AFHTTPSessionManager * manager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:#"" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
[formData appendPartWithFileData:imageData name:#"image" fileName:#"profile.png" mimeType:#"image/png"];
} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[delegate didReceiveRegisterResponse:responseObject];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
but i dont know how to assign that imagedata now.

I Have done it passing NSData and NSDictionary inside array. like below
[self performSelectorInBackground:#selector(reloadPage:)
withObject:[NSArray arrayWithObjects:pageIndex,firstCase,nil] ];
- (void) reloadPage: (NSArray *) args {
NSString *pageIndex = [args objectAtIndex:0];
NSString *firstCase = [args objectAtIndex:1];
}
Got the answer from this question

Related

objective-c,How to send file as a parameter

I want to upload my image from my phone gallery to the server so I am not able to upload my program ,it runs successfully and shows print -
NSLog(#">>>>>>>>>> enter in ");
but it could not upload image on the server ,when I checked it in the app then there is no image ,and I also checked parameter, I think I am not sending proper file format in the parameter.
Please can anyone help me with proper file formate how to convert it
`
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingImage:(UIImage *)img
editingInfo:(NSDictionary *)editingInfo
{
[picker dismissModalViewControllerAnimated:YES];
NSURL *imagePath = [editingInfo objectForKey:#"UIImagePickerControllerReferenceURL"];
imageName = [imagePath lastPathComponent];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
localFilePath = [documentsDirectory stringByAppendingPathComponent:imageName];
NSLog(#"localFilePath.%#",localFilePath);
}
- (IBAction)submitBtn:(id)sender
{
NSURL* url;
url = [NSURL URLWithString:UrlBasic];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
manager.requestSerializer = [AFJSONRequestSerializer serializerWithWritingOptions:NSJSONWritingPrettyPrinted];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
fileURL = [NSURL fileURLWithPath:localFilePath];
reqData=[[NSMutableDictionary alloc]initWithObjectsAndKeys:imageName1,#"image",#"addclassphotoactmobs",#"droot",schoolFolderA,#"schoolfolder",_choseGalleryTextF.text,#"gname",dividNum,#"classid",fileURL,#"uploadedfile",nil];
NSLog(#"reqData=%#",reqData);
[manager POST:UrlBasic parameters:reqData constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { }
progress:nil
success:^(NSURLSessionTask *task, NSMutableDictionary *responseObject) {
NSLog(#" %#",responseObject);
NSLog(#">>>>>>>>>> enter in ");
[self.view makeToast:#"submitted ....."
duration:3.0
position:CSToastPositionCenter];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"error-=%#",error);
// [self.view makeToast:#"Please check internet connection !"];
}];
}
[Updated with imageNameStr]
While uploading your image data, it is necessary to send Name of the file.To generate a file Name, Here I've used Date and time.
Add the Code below the Line NSLog(#"reqData=%#",reqData);
====================
You have missed the formData Code.
Where as the image is the actual image in the below code.
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"yyyyMMddhhmmssSSS"];
NSString *imageNameStr = [NSString stringWithFormat:#"%#.jpg",[formatter stringFromDate:[NSDate date]]];
[sessionManager POST:appendURL
parameters:postParamDict
constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
if(image!=nil){
NSData * imageData = UIImageJPEGRepresentation(image,0.5f);
if(imageData!=nil){
[formData appendPartWithFileData:imageData
name:#"image"
fileName:imageNameStr
mimeType:#"image/jpg"];
}
}
}
progress:^(NSProgress * _Nonnull uploadProgress) {
}
success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
NSLog(#"%#",responseObject);
if(success)
success (responseObject);
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(#"error %#",error);
if(failure)
failure (error);
}]

Create JSONArray of JSONObjects using AFNetworking 2.0 in Objective-C

- The structure that I am trying to create is
[{'category_id': '3'}, {'category_id': '2'}, {'category_id': '1'}]
- I tried creating the same using NSMutableArray of NSMutableDictionary & the structure that i got back was:
<__NSArrayM 0x7c186080>(
{
"category_id" = 1;
},
{
"category_id" = 2;
},
{
"category_id" = 3;
}
)
- I am sending this to server over HTTPPost.
- But on the server the request is reaching as:
{(null)[][category_id]': ['1', '2', '3']}
Which is not in the desired format as i showed above in point 1.
- Can anyone please help me out create an JSONArray of JSONObjects, I would be really obliged.
The code that i used to create and send the request to server is:
-(void) getProductList:(NSString *)strToken andCatId:(NSArray *)arrCategory{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:strToken forHTTPHeaderField:#"Authorization"];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
NSString *strSuffix = #"unfollow/productList/";
NSString *strUrl = [NSString stringWithFormat:#"%#%#",BASE_URL,strSuffix];
api_categoryProductList *currentObj = self;
[manager POST:strUrl parameters:arrCategory success:^(AFHTTPRequestOperation *operation, id responseObject) {
[currentObj httpOperationDidSuccess:oper
ation responseObject:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[currentObj httpOperationDidFail:operation error:error];
}];
}
Try this:
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *id = [NSNumber numberWithInt:1];
for (int i = 0; i < 5; ++i) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:id forKey:#"category_id"];
[array addObject:dict];
}
Right now it has static id as 1. You can change it to whatever value you like.

POST with URL parameters and JSON body in AFNetworking

I'd like to make a POST call that has both URL parameters and a JSON body:
URL http://example.com/register?apikey=mykey
JSON { "field" : "value"}
How can I use two different serializers at the same time with AFNNetworking? Here's my code with the URL parameters missing:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:#"http://example.com/register" parameters:json success:^(AFHTTPRequestOperation *operation, id responseObject) {
I make a post method
/**
* Services gateway
* Method get response from server
* #parameter -> object: request josn object ,apiName: api endpoint
* #returm -> void
* #compilationHandler -> success: status of api, response: respose from server, error: error handling
*/
+ (void)getDataWithObject:(NSDictionary *)object onAPI:(NSString *)apiName withController:(UIViewController*)controller
:(void(^)(BOOL success,id response,NSError *error))compilationHandler {
controller = controller;
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// set request type to json
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
// post request to server
[manager POST:apiName parameters:object success:^(AFHTTPRequestOperation *operation, id responseObject) {
// NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject
options:0
error:&error];
//NSString *JSONString = [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
////
// check the status of API
NSDictionary *dict = responseObject;
NSString *statusOfApi = [[NSString alloc]initWithFormat:#"%#"
,[dict objectForKey:#"OK"]];
// IF Status is OK -> 1 so complete the handler
if ([statusOfApi isEqualToString:#"1"] ) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
compilationHandler(TRUE,responseObject,nil);
} else {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSArray *errorMessages = [responseObject objectForKey:#"messages"];
NSString *message = [errorMessages objectAtIndex:0];
[Utilities showAlertViewWithTitle:apiName message:message];
compilationHandler(FALSE,responseObject,nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSString *message = [NSString stringWithFormat:#"%#",[error localizedDescription]];
NSLog(#"Message is %#", message);
NSString *errorMessage = [NSString stringWithFormat:#"%#",[error localizedDescription]];
if (!([message rangeOfString:#"The request timed out."].location == NSNotFound)) {
[Utilities showAlertViewWithTitle:apiName message:errorMessage];
}
compilationHandler(FALSE,errorMessage,nil);
}];
// For internet reachibility check if changes its state
[self checkInternetReachibility:manager];
}
**for Example when we call the Service **
// calling service gateway API
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
"field",#"value",
nil];
[self getDataWithObject:dict onAPI:KGet_Preferences withController:(UIViewController*)controller :^(BOOL success, id response, NSError *error) {
if( success ) {
NSMutableDictionary *data = [[response valueForKey:#"data"] valueForKey:#"preferences"];
compilationHandler(success,data,error);
} else {
compilationHandler(success,nil,error);
}
}];
I believe there is no automatic way of doing it. However, there is a simple way of achieving it manually:
- (NSMutableURLRequest *)someRequestWithBaseURL:(NSString *)baseUrl
method:(NSString *)method
path:(NSString *)path
uriParameters:(NSDictionary *)uriParameters
bodyParameters:(NSDictionary *)bodyParameters
NSURL *url = [NSURL URLWithString:path relativeToURL:[NSURL URLWithString:baseUrl]];
AFHTTPRequestSerializer *httpRequestSerializer = [AFJSONRequestSerializer serializerWithWritingOptions:0]
NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:bodyParameters];
if ([httpRequestSerializer.HTTPMethodsEncodingParametersInURI containsObject:method]) {
[parameters addEntriesFromDictionary:uriParameters];
} else {
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
// For urlEncodedString, check http://stackoverflow.com/a/718480/856549
urlComponents.percentEncodedQuery = [uriParameters urlEncodedString];
url = [urlComponents URL];
}
NSError *error;
NSURLRequest *request = [httpRequestSerializer requestWithMethod:method
URLString:[url absoluteString]
parameters:parameters
error:&error];

Parse.com and AFNetworking 2.0 Date Queries

I'm trying to use AFNetworking 2.0 to get records from a Parse.com backend. I want to get records updated after a certain date. Parse.com documentation states that comparison queries against a date field need to be url encoded in the format:
'where={"createdAt":{"$gte":{"__type":"Date","iso":"2011-08-21T18:02:52.249Z"}}}'
This works perfectly using curl.
In my app, I am using AFNetworking 2.0 to run the query as below. I first set the request and response serializer when initializing the shared client:
+ (CSC_ParseClient *)sharedClient {
static CSC_ParseClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURL *baseURL = [NSURL URLWithString:#"https://api.parse.com"];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
[config setHTTPAdditionalHeaders:#{ #"Accept":#"application/json",
#"Content-type":#"application/json",
#"X-Parse-Application-Id":#"my app ID",
#"X-Parse-REST-API-Key":#"my api key"}];
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:10 * 1024 * 1024
diskCapacity:50 * 1024 * 1024
diskPath:nil];
[config setURLCache:cache];
_sharedClient = [[CSC_ParseClient alloc] initWithBaseURL:baseURL
sessionConfiguration:config];
_sharedClient.responseSerializer = [AFJSONResponseSerializer serializer];
_sharedClient.requestSerializer = [AFJSONRequestSerializer serializer];
});
return _sharedClient;
}
- (NSURLSessionDataTask *)eventsForSalesMeetingID:(NSString *)meetingID sinceDate:(NSDate *)lastUpdate completion:( void (^)(NSArray *results, NSError *error) )completion {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
[dateFormatter setTimeZone:gmt];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSString *dateString = [dateFormatter stringFromDate:lastUpdate];
NSLog(#"date = %#", dateString);
NSDictionary *params = #{#"where": #{#"updatedAt": #{#"$gte": #{#"__type":#"Date", #"iso": dateString}}}};
NSURLSessionDataTask *task = [self GET:#"/1/classes/SalesMeetingEvents"
parameters:params
success:^(NSURLSessionDataTask *task, id responseObject) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
NSLog(#"Response = %#", httpResponse);
if (httpResponse.statusCode == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(responseObject[#"results"], nil);
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, nil);
});
NSLog(#"Received: %#", responseObject);
NSLog(#"Received HTTP %d", httpResponse.statusCode);
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, error);
});
}];
return task;
}
But this yields a 400 error from the server. The url encoded query string returned looks like this after decoding:
where[updatedAt][$gte][__type]=Date&where[updatedAt][$gte][iso]=2014-01-07T23:56:29.274Z
I tried hard-coding the back end of the querystring like this:
NSString *dateQueryString = [NSString stringWithFormat:#"{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%#\"}}", dateString];
NSDictionary *params = #{#"where":#{#"updatedAt":dateQueryString}};
This gets me closer, but still a 400 error; the returned query string from the server looks like this:
where[updatedAt]={"$gte":{"__type":"Date","iso":"2014-01-07T23:56:29.274Z"}}
How do I get the proper query string from AFNetworking? I started out using the ParseSDK, which made this query super easy, but their SDK is way to heavy (30+ MB).
From the parse.com REST documentation here:
The value of the where parameter should be encoded JSON. Thus, if you look at the actual URL requested, it would be JSON-encoded, then URL-encoded
You are so close with your hardcoded string, you just need to URL-encode the whole query. I have had success with the following:
NSString *dateQueryString = [NSString stringWithFormat:#"{\"updatedAt\":{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%#\"}}}", dateString];
NSDictionary *parameters = #{#"where": dateQueryString};
The following uses an NSDictionary to construct the dateQueryString:
NSString *dateQueryString;
NSDictionary *query = #{ #"updatedAt": #{ #"$gte": #{#"__type":#"Date",#"iso":dateString}}};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:query
options:nil
error:&error];
if (!jsonData) {
NSLog(#"Error: %#", [error localizedDescription]);
}
NSString *dateQueryString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
NSDictionary *parameters = #{#"where": dateQueryString};
For completeness - I am using a shared instance of an AFHTTPSessionManager subclass:
#implementation ParseAPISessionManager
+ (instancetype)sharedSession {
static ParseAPISessionManager *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[ParseAPISessionManager alloc] initWithBaseURL:[NSURL URLWithString:parseAPIBaseURLString]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (self) {
self.requestSerializer = [AFJSONRequestSerializer serializer];
[self.requestSerializer setValue:parseAPIApplicationId forHTTPHeaderField:#"X-Parse-Application-Id"];
[self.requestSerializer setValue:parseRESTAPIKey forHTTPHeaderField:#"X-Parse-REST-API-Key"];
}
return self;
}
And calling it like this:
ParseAPISessionManager *manager = [ParseAPISessionManager sharedSession];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:13];
[comps setMonth:2];
[comps setYear:2014];
[comps setHour:16];
[comps setMinute:0];
NSDate *feb13 = [[NSCalendar currentCalendar] dateFromComponents:comps];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.'999Z'"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSString *feb13str = [dateFormatter stringFromDate: feb13];
NSString *queryStr = [NSString stringWithFormat:#"{\"updatedAt\":{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%#\"}}}", feb13str];
NSDictionary *parameters = #{#"where": queryStr};
[manager GET:#"classes/TestClass" parameters:parameters success:^(NSURLSessionDataTask *operation, id responseObject) {
NSLog(#"%#", responseObject);
} failure:^(NSURLSessionDataTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Sorry for the long post, hope it helps

how to send array as a parameter in Afnetwoking post method?

hi i need to send a array as a one of the parameter in Afnetworking Query String
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://192.008.0.28/aaa/a/"]];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: #"20", #"Miles", [NSArray arrayWithObjects:#"1",#"2",#"3",nil], #"Interval", nil];
[httpClient postPath:iUpdateNotificationMethod parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", responseStr);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
But server side we got "Miles":20,"Intervals":null how to fix it
Thanks,
Try This
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:OAuthBaseURL];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] initWithCapacity:0];
for (int i =0; i < [userIDs count]; i++) {
NSString *userID = [[userIDs objectAtIndex:i] objectForKey:#"id"];
NSDictionary *tmpDict = [NSDictionary dictionaryWithObjectsAndKeys:userID , [NSString stringWithFormat:#"ids[%i]",i], nil];
[parameters addEntriesFromDictionary:tmpDict];
}
[client postPath:#"/user"
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSData *data = (NSData *)responseObject;
NSString *jsonStr = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(#"jsonStr %#",jsonStr);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self showError];
}
];
Since you're submitting an array, AFNetworking is generating a different parameter name and overloads it with the values you supply. For example, your request generates the following querystring:
Interval[]=1&Interval[]=2&Interval[]=3&Miles=20
This is defined in AFHTTPClient.m in the AFQueryStringPairsFromKeyAndValue function.
If you want to keep the original parameter, you should decide how to convert your NSArray to NSString by yourself. For example, you can do something like [myArray componentsJoinedByString:#","] and then split it back to elements on the server. If you choose this method, beware of using characters that might appear in your actual data.
I believe this will work:
params = #{ #"Miles": #"20", #"Interval": #[#"1",#"2",#"3"] };

Resources