I am trying to send wav file as a NSData to rest service with AFNetworking 3. I figured out how to send with AFMultipartFromData but i got an error like that
errorMessage = "Can Not Map Content-Type String multipart/form-data; boundary=Boundary+02588C5 To Media Type ";
When i spoke with the guy who created rest service then he told me i have to send just NSData not anything like AFMultipartFormData. I need some help here because i could not find any way to send "just" NSData.
My code is below;
NSURL *URL = [NSURL URLWithString:#"http://xxxMyService"];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.HTTPAdditionalHeaders = #{#"xx": #"yy ; zz"};
AFHTTPSessionManager *manager2 = [[AFHTTPSessionManager alloc] initWithBaseURL:URL sessionConfiguration:configuration];
manager2.responseSerializer = [AFJSONResponseSerializer serializer];
//I converted wav file to NSData
NSData *data=[self setVoiceRecordToNSData];
[manager2 POST:#"http://xxxMyService" parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
[formData appendPartWithFileData:data name:#"data" fileName:#"Path.wav" mimeType:#"audio/wav"];
}
progress:nil success:^(NSURLSessionTask *task, id responseObject
{ NSLog(#"JSON: %#", responseObject);}
failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error); }];
Try add this code before POST
manager2.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"multipart/form-data"];
Related
This question already has answers here:
afnetworking 3.0 Migration: how to POST with headers and HTTP Body
(10 answers)
Closed 5 years ago.
I am working on a project that using AFNetworking to connect with API interface. My problem is that how to send a request to the backend with body content that includes email, deviceId. I have found many solutions that all compatible with AFNetworking 2.0 not 3.0.
Now I am using SessionManager, when i initialize request, how can I add content body context?
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
NSString *stringData = [[NSString alloc]initWithData:jsonData encoding:NSASCIIStringEncoding];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager.requestSerializer setValue:#"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript", #"text/html", nil];
[manager POST:_urlString parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSString *link = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"JSON: %#",link);
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
I have tried to put email& deviceId into [manager POST parameter: Dict], but it is not working.
Can someone tell me how to add body to AFNetworking 3.0? Thanks
if i got your question correctly it shouldnt be that hard. its similar to the 2.0 version as well.
NSDictionary *parameters = #{#"username": _username.text,
#"deviceId": deviceIdString,
};
NSMutableDictionary * parameters = [[NSMutableDictionary alloc]initWithDictionary:params];
NSURL *baseURL = [NSURL URLWithString:#"http://url.com/ws/test.php"];
AFHTTPSessionManager * manager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:#"" parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
//Response
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if(error.code==-1001){
//Handle the error
}
}];
I'm doing this to send images in an array to server:
NSString *string = [NSString stringWithFormat:#"%#/API/Upload",BaseURLString];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:BaseURLString]];
[manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
[manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
for(NSData *eachImage in self.fetchedAtt) {
[manager POST:string
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
[formData appendPartWithFormData:eachImage
name:#"image1"];
}
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (responseObject != nil)
{
//NSDictionary *jsonDictionary = responseObject;
NSLog(#"%#",responseObject);
}
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(#"%#",error.localizedDescription);
}];
}
For now I only send one image to test. And it get responseObject which is bytes data.
<696d6167 65313a20 efbfbdef bfbdefbf bdefbfbd 00104a46 49460001
01000048 00480000 efbfbdef bfbd0058 45786966 00004d4d 002a0000
00080002 01120003 00000001 00010000 efbfbd69 00040000 00010000
00260000 00000003 efbfbd01 00030000 00010001 0000efbf bd020004
00000001 0000001e efbfbd03...
As per the web guy response should be the URL of the image. Web backend is in ASP.NET What am I doing wrong?
UPDATE
If I change the response serializer I get:
Request failed: unacceptable content-type: application/octet-stream
I've even tried this:
NSString *string = [NSString stringWithFormat:#"%#/API/Upload",BaseURLString];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
[manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
NSError *error;
for(NSData *eachImage in self.fetchedAtt) {
NSURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:#"POST" URLString:string parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
//NSString *value = #"qux";
//NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
//[formData appendPartWithFormData:eachImage name:#"image1"];
[formData appendPartWithFileData:eachImage name:#"image1" fileName:#"test.jpg" mimeType:#"image/jpeg"];
} 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(#"%#", responseObject);
}];
[task resume];
}
But got Request failed: internal server error (500). if I uncomment the appendPartWithFormData and comment other line I get same bytes in responseObject.
More Updates:
We tested it on postman and the image was uploaded successfully. But if I give something in parameter I get
Request failed: unsupported media type (415)
When you upload images, you'd expect some response from the server (just to acknowledge that they were received successfully). Having said that, looking at your hex data, it's curious. What it looks like is:
The "JFIF" and "Exif" references are consistent with a JPEG response. And the image1 looks like it was the name of the image you sent. But this is a very curious response. It's definitely not the URL of the image.
You should contact the web service authors and get details of what precisely they're sending back, because it doesn't conform to standard responses (XML, JSON, etc.).
By the way, your method of uploading the image looks incorrect. You'd usually do something like:
[formData appendPartWithFileData:eachImage
name:#"image1"
fileName:#"test.jpg"
mimeType:#"image/jpeg"];
Clearly, you'd specify the fileName and mimeType to match what the NSData really was. And I'd double check with the author of the web service whether they really want to use a field name of image1 ... that's a little atypical.
I have to make a post request using AFNetworking library with following request parameters
{
"method":"validate",
"name":{
"firstname":"john",
"lastname":"doe"
}
}
How to make this request using latest version of AFNetworking v3 library?
I used the following code and it doesn't work
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
[manager setRequestSerializer:[AFJSONRequestSerializer serializer]];
[manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
NSDictionary *parameters = #{\"method\":\"validate\",\"name\":{\"firstname\":\"john\",\"lastname\":\"doe\"}};
[manager POST:#"http://myUrl.." parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"%#",[responseObject description]);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"%#",[error localizedDescription]);
}];
Im getting the following error,
2016-02-13 11:04:54.085 SlideOutMenu[3698:50453] nulllllll
2016-02-13 11:04:55.794 SlideOutMenu[3698:50453] Failure Request failed: internal server error (500)
2016-02-13 11:04:55.795 SlideOutMenu[3698:50453] (null)
As you've already applied [manager setRequestSerializer:[AFJSONRequestSerializer serializer]] no need to convert dictionary to JSON again.
simply pass dictionary as a parameters, it will work.
NSDictionary *name = #{#"firstname": #"john", #"lastname": #"doe"};
NSMutableDictionary *parameters = [NSMutableDictionary new];
[parameters setObject:#"validate" forKey:#"method"];
[parameters setObject:name forKey:#"name"];
Also no need to initialise NSURLSessionConfiguration with defaultSessionConfiguration, AFNetworking will automatically initialise that. Simply use [AFHTTPSessionManager manager].
Your code is fine.Connect with your server guy.
code 500 is server side error.
check out this link for response code detail
http://www.restapitutorial.com/httpstatuscodes.html
I am trying to send nested json with an image from my ios app using AFNetworking library.I am able to send the json data and image successfully but in server the json structure is coming differently.
HTTP request inside my app :-
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"requestData":#{#"username":#"200OK",#"password":#"password"}};
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:Self_URL
parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImagePNGRepresentation(image)
name:#"file"
fileName:#"file"
mimeType:#"image/jpeg"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
So in my django server I am expecting the params as a dictionary same as params but request.POST is coming as
content_type---> multipart/form-data; boundary=Boundary+247685AB6DF2B3BA
<QueryDict: {'requestData[password]': [u'password'], 'requestData[username]': [u'200OK']}>
How can I send json data so that it will be easy to access from server ?
Anything I am missing or what is going wrong?
constructingBodyWithBlock is overriding your AFJSONRequestSerializer and your dictionary is encoded as form data. There is no way to have two content types (multipart/form-data and application/json) for a request at the same time, so you'll have to do this another way.
One possibility is to encode the JSON as an NSData object and append it to the multipart form along with the image data:
NSError *error = nil;
NSData *paramData = [NSJSONSerialization dataWithJSONObject:params
options:0
error:&error];
[formData appendPartWithFileData:paramData
name:#"params"
filename:#"params"
mimeType:#"application/json"]
You can access the serialized parameters through request.FILES['params']. Despite the mime-type, I doubt that django will automatically parse the JSON data into a dictionary, but you could do that manually with json.loads.
In AFNetworking3.0, you can introduce JSON in a form using the appendPartWithFormData function
[formData appendPartWithFormData:params name:#"params"];
On the server side, you can access the serialized data using json.loads() on the object. Here is a full snippet from some code I wrote:
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST"
URLString:requestUrl parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFormData:[self dictToJson:params] name:#"params"];
[formData appendPartWithFileData:fileData name:fileGeneralName fileName:fileName mimeType:mimeType];
} error:nil];
[[manager uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse* response, id responseObject, NSError* error) {
[self callCompletionBlock:responseObject withError:error withResponse:response completionHandler:completionBlock];
}] resume];
There's a serialization function in that snippet, which I'll also paste for completion:
+(NSData*)dictToJson:(NSDictionary*)dict {
NSError* error = nil;
return [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error]; }
I'm trying to upload a video to YouTube using v3 API using AFNetworking 2.0. The upload itself is working fine and I am able to see a video at my channel. What I'm having a problem is the parameters (the video resource) to specify the title, description etc which I have to put as my request body (along with the video itself) Here is the code I am using.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:#"Bearer #_token_goes_here#" forHTTPHeaderField:#"Authorization"];
NSDictionary *parameters = #{#"snippet" : #{#"title" : #"random_title",
#"description" : #"random_description"}};
NSURL *filePath = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"video" ofType:#"mov"]];
[manager POST:#"https://www.googleapis.com/upload/youtube/v3/videos?part=snippet,status" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:filePath name:#"video" fileName:#"video.mov" mimeType:#"video/*" error:NULL];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
How do I properly set the JSON parameters for the request?
Thanks.
Ok, so if anyone is interested, the only solution I found for this is to send the second PUT update request to set the proper title and description.
You have to append the snippet to the multipart form data
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: parameters options:NSJSONWritingPrettyPrinted error:NULL];
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
[mutableHeaders setValue:[NSString stringWithFormat:#"form-data; name=\"%#\"", #"snippet"] forKey:#"Content-Disposition"];
[mutableHeaders setValue:#"application/json" forKey:#"Content-Type"];
[formData appendPartWithHeaders:mutableHeaders body:jsonData];
[formData appendPartWithFileURL:filePath name:#"video" fileName:#"video.mov" mimeType:#"video/*" error:NULL];
One request, and only need the permissions to upload.