I have an application where on a button click i am passing my server api method which calls the JSON post method and saves data to server database.Here i am saving my mobile number and emergency no to server database.My mobile number is in string format.In my mobile number string variable, my mobile number is getting saved which is in this format '+90-9491491411'.I am entering + and then code and then- and then number but when i send to the server database i am removing the - and sending the no to database but problem is in my server database + of mobile is not getting entered which i am entering .What may be the problem .I am using POST method to send the request .This is my code
-(void)sendRequest
{
NSString *newstring = txtMobile.text;
mobileValue = [newstring stringByReplacingOccurrencesOfString:#"-" withString:#""];
NSLog(#"%#",mobileValue);
NSString *newString1 = txtemergencyprovider.text;
emergencyNumber = [newString1 stringByReplacingOccurrencesOfString:#"-" withString:#""];
NSLog(#"%#",emergencyNumber);
if ([txtEmail.text isEqualToString:#""])
{
post = [NSString stringWithFormat:#"CommandType=new&ApplicationType=%d&FullName=%#&Mobile=%#&EmergencymobileNumber=%#&Latitude=%f&Longitude=%f&City=%#&MobileModel=Apple",applicationtype,txtFullname.text,mobileValue,emergencyNumber,latitude,longitude,txtCity.text];
NSLog(#"%#",post);
}
else {
post = [NSString stringWithFormat:#"CommandType=new&ApplicationType=%d&FullName=%#&Mobile=%#&EmergencymobileNumber=%#&Latitude=%f&Longitude=%f&City=%#&EmailAddress=%#&MobileModel=Apple",applicationtype,txtFullname.text,mobileValue,emergencyNumber,latitude,longitude,txtCity.text,txtEmail.text];
NSLog(#"%#",post);
}
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSLog(#"%#",postLength);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://myapi?RequestType=NEW"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (theConnection) {
webData = [[NSMutableData data] retain];
NSLog(#"%#",webData);
}
else
{
}
}
//In my mobile number and emrgency number variable my no is in this format '+91986444711' but when the value is entered in server database + gets removed off .What may be the prob.
Unfortunately, NSString's -stringByAddingPercentEscapesUsingEncoding: will not convert the plus (+) sign into %2B because the plus sign is a valid URL character that is used to separate query parameters. What this usually means is that it gets converted to a space character by the web server.
The easiest way to replace the plus sign would be using NSString's stringByReplacingOccurrencesOfString:withString: to replace the + with %2B. For example:
mobileValue = [mobileValue stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];
The plus sign ("+") in URL means an encoded space (" ") and most likely your server will interpret it as a space. Change the plus character to %2B in the string before posting it. For a complete solution on URL encoding see this post: http://madebymany.com/blog/url-encoding-an-nsstring-on-ios
The plus sign means space in a post request. You need to convert the plus to a percent escape character. The easiest way to do this is as follows:
NSString* escapedMobileValue = [mobileValue stringByReplacingOccurencesOfString: #"+" withString: #"%2b"];
This will turn the + into %2b. Probably the server will automatically reverse the encoding for you.
(Edited in line with mttrb's comment)
Related
For some reason i can't upload a jpeg file to a server using the post method in NSURLRequest
I have an android app that uses the same php code and can upload and download images fine by converting the image to a byte array and then using base64 encoding to send and receive.
My iPhone app downloads the image fine, The php script encodes using base64 and i use a base64 decoder in my iPhone app which I then convert into an image. This works fine.
However the uploading of the image doesn't work.
I convert the image to a base64 encoded string (I've used a few different methods for the base64 encoding and they all give the same result) then I post to the server, decode on the server side and save to file on the server.
The resulting decoded file on the server is a corrupt jpeg image. The corrupt file size is 3 times as many bytes as it should be.
The base64 encoded string generated for the upload is also very different to the base64 encoded string generated when downloading the same jpeg file from the server (ie. the valid image file that I uploaded using an ftp service).
My code is shown below along with the php script to receive the image.
I believe there is something happening with escaping characters which is causing the base64 string to become corrupted during the transfer but can't work it out.
Why is my base64 string being corrupted during transfer?
NSString* comments = #"comments to go with image";
NSData *data = UIImageJPEGRepresentation(_imageView.image, 1);
NSString *base64EncodedImage = [NSString base64StringFromData: data length: data.length];
//load the team posts so we know what items have been posted and what haven't
NSMutableDictionary *postDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
comments, #"comment",
base64EncodedImage , #"image",
nil];
NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in postDict) {
NSString *part = [NSString stringWithFormat: #"%#=%#", key, [postDict objectForKey:key]];
[parts addObject:part];
}
NSString *encodedDictionary = [parts componentsJoinedByString:#"&"];
NSData *postData = [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
NSString* url = #"http://www.scroppohunt.com/upload.php";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:10.0];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d", postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
_data = [[NSMutableData data] init];
}
and the php script that receives the image
<?php
$comments = $_REQUEST['comment'];
//do some database stuff with the comments
////////////////////////////////////////
//save the file to the images folder
///////////////////////////////////////////
$base=$_REQUEST['image'];
if(strlen($base) > 0)
{
// base64 encoded utf-8 string
$binary=base64_decode($base);
$file = fopen("postImages/test.jpg", 'wb');
fwrite($file, $binary);
fclose($file);
}
//display the bae64 encoded string taht was uploaded
echo $base;
?>
Well, it's been a while when you asked this question, but if anyone (like me) find this question, this may help:
In your Base64 encoded image, you should replace all occurrences of "+" character, with "%" character. Translated into code, it would be:
NSString* encodedImageString = [base64EncodedImage stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];
Then, instead of adding base64EncodedImage in postDict, you should add encodedImageString.
That way, your postDict will look like this:
NSMutableDictionary *postDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
comments, #"comment",
encodedImageString , #"image",
nil];
I think this will solve the problem, at least, was for me.
Cheers.
I also had this problem. For me, what was happening was that all the "+" were replaced with "space" after being sent to the server. There was no other such corruption:
Try Changing content type.
[request setValue:#"image/jpeg" forHTTPHeaderField:#"Content-Type"];
I have a method that periodically sends data to a server and receives a response code back. I implemented NSURLConnection's sendAsynchronousRequest for it, and it was working with small data fine. I've had a chance to test sending base64 encoded pictures, which is a common task for the app, and am finding that it cuts off after a few characters of the encoded image. Here's the code involved.
// Initial setup
NSString *urlStr = #"https://example.com/";
urlRequest = [[NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr]] retain];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[urlRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
// The actual sending part
- (void)sendRequest:(NSString *)reqStr {
#try {
if (sendRequestStatus == kRequestState_waiting) {
sendRequestStatus = kRequestState_processing;
NSString *dataStr = [NSString stringWithFormat:#"request_data=%#",reqStr];
NSLog(#"datastr is %#",dataStr);
NSData *dataForUrl = [dataStr dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"nsdata length is: %i",[dataForUrl length]);
[urlRequest setHTTPBody:dataForUrl];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *res, NSData *data, NSError *err) {
// housekeeping
}];
}
}
I get no errors in the logs. The log statement that prints out the dataStr prints the correct data. The log statement that prints the length of the data printed out 183384 bytes, which seems appropriate for the picture. On the server however, the post body is cut off a few characters after the start of the encoded image data. An example is /9j/4 where 4 was the last character the server received.
I'm testing this on an iPhone 3Gs. This is a phonegap application, and testing the same on my Android version has no issues, so the problem must be in my implementation of sending the data. I have not heard any problems from another tester using an iPhone 4 or 4s, so it could be an issue of processing speed. What can I do to tighten this up and prevent the post body from ever cutting off?
I didn't test it, but maybe the problem is this:
[urlRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
I would try with this:
[urlRequest setValue:#"text/plain" forHTTPHeaderField:#"Content-Type"];
because you are sending a base 64 encoded string.
I have been trying out for a while using Box 2.0 API to upload a file from Objective C client to my Box folder. I've read a few posts from:
how to send form data in a programmatic file upload in box api 2.0
API 2.0 how to upload file with POSTMAN?
I've tried successfully using the Curl, as mentioned in the documentation, but always get a 404 when trying to create a NSMutableUrlRequest.
This is my code:
NSURL *URL = [NSURL URLWithString:#"https://api.box.com/2.0/files/content"];
urlRequest = [[NSMutableURLRequest alloc]
initWithURL:URL cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30];
[urlRequest setHTTPMethod:#"POST"];
AppDelegate *appDelegate = [AppDelegate sharedDelegate];
NSString *p = [NSString stringWithFormat:#"BoxAuth api_key=%#&auth_token=%#",API_KEY,appDelegate.boxAuthToken];
[urlRequest setValue:p forHTTPHeaderField:#"Authorization"];
[urlRequest setValue:#"multipart/form-data, boundary=AaB03x" forHTTPHeaderField:#"Content-Type"];
NSString *postBody = #"--AaB03x"
#"content-disposition: form-data; name=\"filename\"; filename=\"test.txt\";"
#"folder_id=466838434"
#"Content-type: text/plain"
#""
#"testing box api 2.0"
#""
#"--AaB03x--";
NSData *data = [postBody dataUsingEncoding:NSUTF8StringEncoding];
[urlRequest setHTTPBody:data];
[urlRequest setValue:[NSString stringWithFormat:#"%d",[data length]] forHTTPHeaderField:#"Content-Length"];
There are a couple of problems that I see with the way you're constructing the postBody. Having newlines between string literals in your code simply concatenates them. You actually need to have carriage return and line feed to separate different parts of your HTTP body. Also, you mashed both of your form elements in one. The file and folder_id are two separate form elements. You could try something like this:
NSString *postBody = #"\r\n--AaB03x\r\n"
"Content-Disposition: form-data; filename=\"test.txt\"\r\n"
"Content-Type: text/plain\r\n\r\n"
"testing box api 2.0"
"\r\n--AaB03x\r\n"
"Content-Disposition: form-data; name=\"folder_id\";\r\n\r\n"
"0"
"\r\n--AaB03x--\r\n\r\n";
I think that should work provided everything else is set up properly.
Use http://allseeing-i.com/ASIHTTPRequest/
It makes dealing with multipart forms much easier!
I am attempting to implement an online leaderboard in a game app for iOS, using Django to process POST requests from the iDevice and store the scores. I have figured out how to get Django to serialize the objects to XML, and my iPhone can read and display the scores. However, I can't for the life of me get my iPhone to POST XML to my Django server.
Below is the function I am using to post the scores...
iOS (Objective-C) Controller:
- (void) submitHighScore {
NSLog(#"Submitting high score...");
NSString *urlString = HIGH_SCORES_URL;
NSURL *url = [NSURL URLWithString: urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url];
[request setHTTPMethod: #"POST"];
[request setValue: #"text/xml" forHTTPHeaderField: #"Content-Type"];
NSMutableData *highScoreData = [NSMutableData data];
[highScoreData appendData: [[NSString stringWithFormat: #"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"<player_name>%#</player_name", #"test"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"<score>%d</score>", 0] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"</xml>"] dataUsingEncoding: NSUTF8StringEncoding]];
[request setHTTPBody: highScoreData];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest: request
delegate: self];
if (!connection) {
NSLog(#"Request to send high scores appears to be invalid.");
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: NO];
}
}
The above method succeeds in sending the request, and interprets it correctly as CONTENT_TYPE: text/xml, but the Django view that processes the request can't seem to make any sense of it, interpreting it almost as if it was merely plain text. Below is my Django view...
Django (Python) view:
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core import serializers
from django.core.exceptions import ValidationError
from django.views.decorators.csrf import csrf_exempt
from modologger.taptap.models import HighScore
#csrf_exempt
def leaderboard( request, xml = False, template_name = 'apps/taptap/leaderboard.html' ):
"""Returns leaderboard."""
if xml == True: # xml is set as True or False in the URLConf, based on the URL requested
if request.method == 'POST':
postdata = request.POST.copy()
print postdata
# here, postdata is evaluated as:
# <QueryDict: {u'<?xml version': [u'"1.0" encoding="UTF-8" ?><player_name>test</player_name<score>0</score></xml>']}>
for deserialized_object in serializers.deserialize('xml', postdata): # this fails, returning a 500 error
try:
deserialized_object.object.full_clean()
except ValidationError, e:
return HttpResponseBadRequest
deserialized_object.save()
else:
high_score_data = serializers.serialize( 'xml', HighScore.objects.all() )
return HttpResponse( high_score_data, mimetype = 'text/xml' )
else:
high_scores = HighScore.objects.all()
return render_to_response( template_name, locals(), context_instance = RequestContext( request ) )
To be honest, I'm not sure whether the problem lies in the Objective-C or in the Django code. Is the Objective-C not sending the XML in the right format? Or is the Django server not processing that XML correctly?
Any insight would be much appreciated. Thanks in advance.
Update:
I got it to work, by editing the iOS Controller to set the HTTPBody of the request like so:
NSMutableData *highScoreData = [NSMutableData data];
[highScoreData appendData: [[NSString stringWithFormat: #"player_name=%#;", #"test"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"score=%d", 0] dataUsingEncoding: NSUTF8StringEncoding]];
[request setHTTPBody: highScoreData];
For some reason putting a semicolon in there got Django to recognize it, assign the values to a new instance of a HighScore class, and save it. The logging on the test server indicates request.POST is <QueryDict: {u'score': [u'9'], u'player_name': [u'test']}>.
Still not quite sure what to make of all this.
As per Radu's suggestion, I took a look at highScoreData with NSLog, right after appending it to request.HTTPBody, and the result is <706c6179 65725f6e 616d653d 74657374 3b73636f 72653d39>.
I'm a huge Obj-C noob, so again, any help is appreciated! Thanks again.
Since you control both sides, I'd drop the complexity of xml encoding the data and use RestKit or some other framework that makes it easy to communicate with Django.
how to send a transition receipt along with a product identifier to my server using HTTP POST method? Should I have to encode the product identifier using base64?
I am getting this response:
{"message" : "21002: java.lang.IllegalArgumentException: propertyListFromString parsed an object, but there's still more text in the string. A plist should contain only one top-level object. Line number: 1, column: 2478.", "error" : 1}
even after I am encoding the transition receipt with base64 encoding...
This is what I am doing:
NSString *bodyString = [NSString stringWithFormat:#"product_id=%#&receipt_data=%#",self.currentProductIdentifer,
[self.productReceiptData base64Encoding]];
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding
allowLossyConversion:YES];
NSAssert(bodyData!=nil,#"HTTP Body is empty !");
//posting the data to server
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:
[NSURL URLWithString:inUrlString]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody:inData]; //inData is http body(bodyData) created above
// create the connection with the request // and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];