I am stuck on a uploading issue. Server is in dotnet. Here is my iPhone code:
-(NSString *)encodeToBase64String:(UIImage *)image {
return [UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
This works well, but when I am trying to upload by my Android app, it always returns error from server when there some special characters in url like (=).
See below the code:
Bitmap icon = BitmapFactory.decodeResource(this.contextParam.getResources(),
ByteArrayOutputStream bao = new ByteArrayOutputStream();
icon.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte[] ba = bao.toByteArray();
String ba1 = Base64.encodeToString(ba, Base64.DEFAULT);
Log.e("Data:", ba1);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("username", "dsfsdfsd"));
nameValuePairs.add(new BasicNameValuePair("filenamewithextension", "upload.png"));
nameValuePairs.add(new BasicNameValuePair("newfilename", "Testing upload"));
nameValuePairs.add(new BasicNameValuePair("entityid", "10"));
nameValuePairs.add(new BasicNameValuePair("filestream", ba1));
Log.i(TAG, httppost.getURI().toString());
Log.d(TAG, nameValuePairs.toString());
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
String base64EncodedCredentials = Base64.encodeToString(CREDENTIALS.getBytes(), Base64.NO_WRAP);
httppost.addHeader("Authorization", "Basic " + base64EncodedCredentials);
httppost.addHeader("Content-Type", "application/largedata");
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
return getStringFromInputStream(response.getEntity().getContent());
} catch (ClientProtocolException e) {
Log.e(TAG, e.getLocalizedMessage());
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage());
}
return responseString;
With above code server always returns with "Request Error". Why might this be happening?
Aside: I can't change the server implementation, I have to find a solution on the Android side.
I'm not 100% sure because you didn't post your log, but I had a similar issue with an App I was working on for iOS. For HTTP, they have encoding rules. You may need to "percent-escape encode" your HTTPPost.
For example:
www.website.com/security/authorizekey?url=www.website.com?user=bob
When the above link was used as my URL Post, the rules of HTTP truncated my Post so that the server only received "www.website.com/security/authorizekey?url=www.website.com?user=" and truncated my user "bob".
According to RFC 3986, the characters that should be permitted unescaped are the alphanumeric characters, plus "-", ".", "_", and "~":
2.3. Unreserved Characters
Characters that are allowed in a URI but do not have a reserved purpose are called unreserved. These include uppercase and lowercase letters, decimal digits, hyphen, period, underscore, and tilde.
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
See section 2 of the aforementioned RFC 3986 for more information.
Anyways, a solution might be similar to the following:
Potential Solution:
String query = URLEncoder.encode("apples oranges", "utf-8");
String url = "http://stackoverflow.com/search?q=" + query;
Related
I am trying to post xml data to API using HTTP post method with credentials but a getting HTTP/1.1 400 Bad Request error .. Can anyone pl help me out ....
Here is my sample code:
BufferedReader br = new BufferedReader(new FileReader(new File("Data.xml")));
StringBuilder sb = new StringBuilder();
while((line=br.readLine())!= null){
sb.append(line.trim());
}
System.out.println("xml: "+sb);
params=sb.toString();
HttpPost request = new HttpPost("*****************url***************");
String urlaparam=URLEncoder.encode("importFormatCode:1&data:"+params,"UTF-8");
String userCredentials = "****:******";
byte[] auth = Base64.encodeBase64(userCredentials.getBytes());
StringEntity entity=new StringEntity(urlaparam);
request.addHeader("Content-type","application/x-www-form-urlencoded");
request.addHeader("Accept", "application/xml");
request.addHeader("Accept-Language", "en-US,en;q=0.5");
request.addHeader("Authorization", "Basic " + new String(auth));
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);
System.out.println(response.getStatusLine());
System.out.println(request);
}
catch(Exception e)
{
}
First of all, your form parameters are not encoded correctly. You are using colon (:) to separate keys from their values, but instead, the equal sign (=) must be used:
Wrong: "importFormatCode:1&data:" + params
Correct: "importFormatCode=1&data=" + params
(See also W3C.org - Forms in HTML Documents - application/x-www-form-urlencoded)
Apart from that, you must not URL-encode the entire string but only the keys and the values. Otherwise you'll also encode the separator characters = and &!
The easiest way is to use the existing utility class org.apache.http.client.utils.URLEncodedUtils (assuming that you're using Apache HTTP Components):
String xmlData = // your xml data from somewhere
List<NameValuePair> params = Arrays.asList(
new BasicNameValuePair("importFormatCode", "1"),
new BasicNameValuePair("data", xmlData)
);
String body = URLEncodedUtils.format(params, encoding); // use encoding of request
StringEntity entity = new StringEntity(body);
// rest of your code
I intend to send a simple http post request with a large string in the Payload.
So far I have the following.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("address location");
String cred = "un:pw";
byte[] authEncBytes = Base64.encodeBase64(cred.getBytes());
String authStringEnc = new String(authEncBytes);
httppost.setHeader("Authorization","Basic " + authStringEnc);
However, I do not know how to attach a simple RAW string into the payload. The only examples I can find are name value pairs into the Entity but this is not what I want.
Any assistance?
It depends on the concrete HTTP-API you're using:
Commons HttpClient (old - end of life)
Since HttpClient 3.0 you can specify a RequestEntity for your PostMethod:
httpPost.setRequestEntity(new StringRequestEntity(stringData));
Implementations of RequestEntity for binary data are ByteArrayRequestEntity for byte[], FileRequestEntity which reads the data from a file (since 3.1) and InputStreamRequestEntity, which can read from any input stream.
Before 3.0 you can directly set a String or an InputStream, e.g. a ByteArrayInputStream, as request body:
httpPost.setRequestBody(stringData);
or
httpPost.setRequestBody(new ByteArrayInputStream(byteArray));
This methods are deprecated now.
HTTP components (new)
If you use the newer HTTP components API, the method, class and interface names changed a little bit, but the concept is the same:
httpPost.setEntity(new StringEntity(stringData));
Other Entity implementations: ByteArrayEntity, InputStreamEntity, FileEntity, ...
i was making a common mistake sequence of json object was wrong. for example i was sending it like first_name,email..etc..where as correct sequence was email,first_name
my code
boolean result = false;
HttpClient hc = new DefaultHttpClient();
String message;
HttpPost p = new HttpPost(url);
JSONObject object = new JSONObject();
try {
object.put("updates", updates);
object.put("mobile", mobile);
object.put("last_name", lastname);
object.put("first_name", firstname);
object.put("email", email);
} catch (Exception ex) {
}
try {
message = object.toString();
p.setEntity(new StringEntity(message, "UTF8"));
p.setHeader("Content-type", "application/json");
HttpResponse resp = hc.execute(p);
if (resp != null) {
if (resp.getStatusLine().getStatusCode() == 204)
result = true;
}
Log.d("Status line", "" + resp.getStatusLine().getStatusCode());
} catch (Exception e) {
e.printStackTrace();
}
return result;
Answer
I am struggling with creating a plain text file on a server via HTTP PUT. I am using apache commons httpClient. My credentials are working but there is no body content in my request. What must I do to create the file like this? It works as intended when I try via hurl.it (ie setting my credentials, and setting a body). What I would like is the string "hej" to show in the file body. After getting this to work I intend to use a JSONString. The following code generates an empty file on the server (204 response):
HttpClient httpClient = new DefaultHttpClient();
String encoding = http_username + ":" + http_password;
encoding = Base64.encodeBase64String(encoding.getBytes());
HttpPut httpput = new HttpPut(http_path);
HttpEntity content=null;
try{
content = new StringEntity("hej");
}
catch(UnsupportedEncodingException e){
logger.error("Failed to Encode result");
}
logger.info("executing request " + httpput.getRequestLine());
try {
httpput.setHeader("Authorization", "Basic " + encoding);
//httpput.setHeader("Content-Type", "application/json; charset=utf-8");
httpput.setEntity(content);
HttpResponse response = httpClient.execute(httpput);
Header[] allHeaders = response.getAllHeaders();
for (Header h : allHeaders) {
logger.info(h.getName() + ": " + h.getValue());
}
} catch (Exception e) {
logger.error(e.getMessage());
}
I have tried both setting a content type and not doing it, no difference. What basic thing am I doing wrong?
Turns out that Base64.encodeBase64String appends a newline character at the end of the string, which throws everything off!
String encoding = http_username + ":" + http_password;
encoding = Base64.encodeBase64String(encoding.getBytes());
encoding= encoding.replace("\r\n", ""); //This fixes everything
Wow, that just took me a couple of days to figure out!
I am relatively new to Java and have been stuck for a few days trying to get my application to 'POST' a HTTP request to Amazon's MWS API. I keep getting a 'SignatureDoesNotMatch' response and I cannot figure out why. I have used Amazon's MWS scratchpad extensively, and using it I don't have any trouble getting successful responses, so my keys etc are OK. The content parameters and base64 signature generated by the scratchpad match what my application generates, so I am confident that my application is correctly compiling the parameters and signature. When I hardcode the content parameters generated by the scratchpad into my application I get the 'SignatureDoesNotMatch'error response. I would be very grateful for any pointers from more experienced Java developers or anyone who has produced an application like mine working on Amazon's MWS.
The relevant section of my code is:
/*
* get amazon timestamp
*/
GetAmazonTimestamp timestampObj = new GetAmazonTimestamp();
String amazonTimestamp = null;
try {
amazonTimestamp = timestampObj.getTimestamp();
amazonTimestamp.replace(".000Z", "Z");
} catch (IOException e) {
e.printStackTrace();
}
/*
* create http parameters and initialise the signature value
*/
String URLendpoint = "https://mws.amazonservices.co.uk/orders/2011-01-01";
String param1 = "AWSAccessKeyId"; String value1 = "AKIAIZXBKLVSGBBQQL2A";
String param2 = "Action"; String value2 = "ListOrders";
String param3 = "LastUpdatedAfter"; String value3 = "2013-02-01T00:00:00Z";
String param4 = "MarketplaceId.Id.1"; String value4 = "A1F83G8C2ARO7P";
String param5 = "SellerId"; String value5 = "A3A2272JFHXROO";
String param6 = "SignatureMethod"; String value6 = "HmacSHA256";
String param7 = "SignatureVersion"; String value7 = "2";
String param8 = "Timestamp"; String value8 = amazonTimestamp;
String param9 = "Version"; String value9 = "2011-01-01";
String param10 = "Signature"; String value10 = null;
/*
* build sections of URL components for signature
*/
String URLforSignature = "POST\n" + "mws.amazonservices.co.uk\n" + "/Orders/2011-01-01\n" +
URLEncoder.encode(param1,"UTF-8") + "=" +
URLEncoder.encode(value1,"UTF-8") + "&" +
URLEncoder.encode(param2,"UTF-8") + "=" +
URLEncoder.encode(value2,"UTF-8") + "&" +
URLEncoder.encode(param3,"UTF-8") + "=" +
URLEncoder.encode(value3,"UTF-8") + "&" +
URLEncoder.encode(param4,"UTF-8") + "=" +
URLEncoder.encode(value4,"UTF-8") + "&" +
URLEncoder.encode(param5,"UTF-8") + "=" +
URLEncoder.encode(value5,"UTF-8") + "&" +
URLEncoder.encode(param6,"UTF-8") + "=" +
URLEncoder.encode(value6,"UTF-8") + "&" +
URLEncoder.encode(param7,"UTF-8") + "=" +
URLEncoder.encode(value7,"UTF-8") + "&" +
URLEncoder.encode(param8,"UTF-8") + "=" +
URLEncoder.encode(value8,"UTF-8") + "&" +
URLEncoder.encode(param9,"UTF-8") + "=" +
URLEncoder.encode(value9,"UTF-8");
/*
* hash and base64 encode the signature using the URLforSignature
*/
GetAmazonSignature signatureObj = new GetAmazonSignature();
value10 = signatureObj.getSignature(URLforSignature);
/*
* create the http post
*/
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(URLendpoint);
String line = null;
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
nameValuePairs.add(new BasicNameValuePair(param1, value1));
nameValuePairs.add(new BasicNameValuePair(param2, value2));
nameValuePairs.add(new BasicNameValuePair(param3, value3));
nameValuePairs.add(new BasicNameValuePair(param4, value4));
nameValuePairs.add(new BasicNameValuePair(param5, value5));
nameValuePairs.add(new BasicNameValuePair(param6, value6));
nameValuePairs.add(new BasicNameValuePair(param7, value7));
nameValuePairs.add(new BasicNameValuePair(param8, value8));
nameValuePairs.add(new BasicNameValuePair(param9, value9));
nameValuePairs.add(new BasicNameValuePair(param10, value10));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
line = "";
while ((line = rd.readLine()) != null) {
System.out.println(line);
}
}
Thanks for your help.
Thanks to those who helped me with this, but I finally worked out that "https://mws.amazonservices.co.uk/orders/2011-01-01" needs a capital "O" in orders. Amazon's development support agree that the 'SignatureDoesNotMatch' error message is not very helpful in this case and have said that they will look into it.
Thanks again
Why not use the Java Client libraries Amazon provides for MWS?
Go to MWS and click on the API you are interested in. You will see a Java Client library link where you can go and get the files you need. They contain examples and will handle the URL signing, parsing, and other work you would normally have to do yourself.
The way you construct URLforSignature seems okay.
You aren't showing your code for GetAmazonSignature, though. I would suspect the flaw to be in there. May be you forgot to base64-encode your result? Note that the MWS scratchpad shows both the hex signature as well as the base64 encoded one on the "Request Details" page. You should be able to find the flaw by comparing those details with your function results.
Here is my code:
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "android");
HttpGet request = new HttpGet();
request.setHeader("Content-Type", "text/plain; charset=utf-8");
Log.d("URL", convertURL(URL));
request.setURI(new URI(URL));
HttpResponse response = client.execute(request);
bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer stringBuffer = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
I don't know which error in my URL:
http://localhost/CyborgService/chatservice.php?action=recive_game&nick_sender=mkdarkness&pass=MV030595&date_last=2012-11-18 09:46:37&id_game=1
I have already used a function to convert URL, but has not worked. But, if I trying open this URL in my Browser, it opens successfully.
Here is my error:
11-18 21:46:37.766: E/GetHttp(823): java.net.URISyntaxException: Illegal character in query at index 127: http://192.168.0.182/CyborgService/chatservice.php?action=recive_game&nick_sender=mkdarkness&pass=MV030595&date_last=2012-11-18 09:46:37&id_game=1
There is a space in your URL, in position 127. The date is generated as "date_last=2012-11-18 09:46:37", which causes an error when opening the URL.
Spaces are not formally accepted in URLs, although your browser will happily convert it to "%20" or to "+", both valid representations of a space in a URL. You should escape all characters: you can replace space with "+" or just pass the String through URLEncoder and be done with it.
To use URLEncoder see e.g. this question: encode with URLEncoder only parameter values, not the full URL. Or use one of the constructors for URI which have a few parameters, not a single one. You are not showing the code that constructs the URL so I cannot comment on it explicitly. But if you have a map of parameters parameterMap it would be something like:
String url = baseUrl + "?";
for (String key : parameterMap.keys())
{
String value = parameterMap.get(key);
String encoded = URLEncoder.encode(value, "UTF-8");
url += key + "&" + encoded;
}
Some other day we can talk about why Java requires to set the encoding and then requires that the encoding be "UTF-8", instead of just using "UTF-8" as the default encoding, but for now this code should do the trick.
There is a whitespace character:
...2012-11-18 09:46:37... (at index 127, just like the error message says).
Try replacing it with %20
Do this way it will definetly help you
HttpClient myClient = new DefaultHttpClient();
HttpPost myConnection = new HttpPost("http://192.168.1.2/AndroidApp/SendMessage");
try {
//Your parameter should be as..
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("messageText", msgText));
nameValuePairs.add(new BasicNameValuePair("senderUserInfoId", loginUserInfoId));
//set parameters to ur URL
myConnection.setEntity(new UrlEncodedFormEntity(nameValuePairs));
//execute the connection
HttpResponse response = myClient.execute(myConnection);
}
catch (ClientProtocolException e) {
//e.printStackTrace();
} catch (IOException e) {
//e.printStackTrace();
}