Error reading xml from doPost HttpServletRequest - java

I am trying to read the XML file being posted using http doPost method. While parsing using SAXParser it throws an Exception:
Content is not allowed in prolog.
The doPost code is:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
{
ServletInputStream httpIn = request.getInputStream();
byte[] httpInData = new byte[request.getContentLength()];
StringBuffer readBuffer = new StringBuffer();
int retVal = -1;
while ((retVal = httpIn.read(httpInData)) != -1)
{
for (int i=0; i<retVal; i++)
{
readBuffer.append(Character.toString((char)httpInData[i]));
}
}
System.out.println("XML Received" + readBuffer);
try
{
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
ByteArrayInputStream inputStream = new ByteArrayInputStream(
readBuffer.toString().getBytes("UTF-8"));
final XmlParser xmlParser = new XmlParser();
parser.parse(inputStream, xmlParser);
}
catch (Exception e)
{
System.out.println("Exception parsing the xml request" + e);
}
}
This is the JUnit I am testing with:
public static void main(String args[])
{
StringBuffer buffer = new StringBuffer();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
buffer.append("<person>");
buffer.append("<name>abc</name>");
buffer.append("<age>25</age>");
buffer.append("</person>");
try
{
urlParameters = URLEncoder.encode(buffer.toString(), "UTF-8");
}
catch (Exception e1)
{
e1.printStackTrace();
}
String targetURL = "http://localhost:8888/TestService";
URL url;
HttpURLConnection connection = null;
try
{
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Content-Length", "" +
Integer.toString(urlParameters.getBytes("UTF-8").length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
}
catch (Exception e)
{
e.printStackTrace();
}
The XML output in the servlet that I am getting is something like this:
XML Received %3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3Cperson%3E%
So this is throwing an exception in SAXparser:
What am I doing wrong? Am I sending the XML in wrong way or reading it wrong way?

You assume
httpInData[i]
is a char, while it is a byte. Your content being UTF-8, that makes a big difference. Use a Reader instead.
Then, you are URLEncoding your XML, which is useless, as it is a POST data. Don't encode it, simply send the data.
replace
urlParameters = URLEncoder.encode(buffer.toString(), "UTF-8");
by
urlParameters = buffer.toString();
Also, the name urlParameter is poorly chosen, as this is a single post body, doesn't go in the url, and isn't really a parameter.

Related

Receiving null Value while using POST method in servlet?

I want to send a string by using POST method in servlet so that it can communicate with other servlet application present in other domain. But I am receiving null in my Input steam object.
My Code:
String content = "10 141 nahush123 01";
URL url = new URL("http://52.220.37.12:8080/servers/servers");
System.out.println(url.toString());
HttpURLConnection httpCon = (HttpURLConnection)url.openConnection();
httpCon.setDoInput(true);
httpCon.setDoOutput(true);
httpCon.setRequestMethod("POST");
httpCon.setRequestProperty("Content-Type", "text/plain;charset=UTF-8");
OutputStream os = httpCon.getOutputStream();
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(os));
out.write(content);
//br = BufferReader(out);
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
writer.println(httpCon.getResponseMessage());
httpCon.connect();
br = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
//reading response
//String resp;
//if(br != null){
content = br.readLine();
//}
System.out.println(content);
writer.println(content);
out.flush();
writer.flush();
writer.close();
out.close();
os.close();
Copy pasted your code in my servlet worked fine
Check that you overrided doPost method in the servlet
Check that you that your post metod work fine and return value, I use "DHC Rest Client" plugin for chrome. It is very cool tool
Try to remove httpCon.connect() line. It is not necessary.
From oracle docs about connect() method:
Operations that depend on being connected, like getContentLength, will
implicitly perform the connection, if necessary.
Operations getResponseMessage, getResponseCode perform the connection.
UPDATED
I tried to test with my local test url and it works. Then i tried with your url and it does not work.
You need to flush output stream before use input stream.
This code work and return "0#5#26#Temperature#Living_Room#555555581#0+0#7#0#Room1#Master_bedroom#555555581#1+1#7#0#Door1#Living_Room#555555581#2+1#6#0#frontdoor#Living_Room#555555581#2+0#6#0#doorback#Balcony#555555581#2+"
PrintWriter writer = res.getWriter();
String content = "10 141 nahush123 01";
URL url = new URL("http://52.220.37.12:8080/servers/servers");
System.out.println(url.toString());
HttpURLConnection httpCon = (HttpURLConnection)url.openConnection();
httpCon.setDoInput(true);
httpCon.setDoOutput(true);
httpCon.setRequestMethod("POST");
httpCon.setRequestProperty("Content-Type", "text/plain;charset=UTF-8");
OutputStream os = httpCon.getOutputStream();
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(os));
out.write(content);
out.flush();
//br = BufferReader(out);
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
writer.println(httpCon.getResponseMessage());
//httpCon.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
//reading response
//String resp;
//if(br != null){
content = br.readLine();
//}
System.out.println(content);
writer.println(content);
writer.flush();
writer.close();
out.close();
os.close();
Try with getparameter() function in the servlet
Call this method with your pass string parameter:
public String postData(String reqStr) {
ObjectOutputStream objOS = null;
ObjectInputStream objIS = null;
HttpURLConnection servletCon = null;
try {
if (reqStr != null) {
Thread.sleep(1000);
objOS.writeObject(reqStr);
} else {
throw new Exception("request is null.");
}
} catch (Exception ex) {
logger.error("Failed to send request to server.", ex);
}
String response = null;
try {
objIS = new ObjectInputStream(servletCon.getInputStream());
response = (String) objIS.readObject();
} catch (Exception ex) {
logger.error("Failed to get response from server.", ex);
response = null;
}
return response;
}
Initializing Connection like you but calling differently:
public void initializeUrlConnection(String servletURL, String contentType, String method) {
try {
logger.debug("Servlet URL " + servletURL);
url = new URL(servletURL);
servletCon = (HttpURLConnection) url.openConnection();
servletCon.setUseCaches(false);
servletCon.setDefaultUseCaches(false);
servletCon.setDoInput(true);
servletCon.setDoOutput(true);
servletCon.setRequestProperty("Content-Type", contentType);
servletCon.setRequestMethod(method);
objOS = new ObjectOutputStream(servletCon.getOutputStream());
} catch (IOException ex) {
logger.error("Failed to initialize Http Connection.", ex);
}
}
First of call initialize connection method with required parameter:
Object.initializeUrlConnection(url, contentType,method);
then call posDataMethod with your string/json parameter:
Object.postData(str);

Java passing parameters to parse.com cloud code function using REST [duplicate]

I am successfully using this code to send HTTP requests with some parameters via GET method
void sendRequest(String request)
{
// i.e.: request = "http://example.com/index.php?param1=a&param2=b&param3=c";
URL url = new URL(request);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "text/plain");
connection.setRequestProperty("charset", "utf-8");
connection.connect();
}
Now I may need to send the parameters (i.e. param1, param2, param3) via POST method because they are very long.
I was thinking to add an extra parameter to that method (i.e. String httpMethod).
How can I change the code above as little as possible to be able to send paramters either via GET or POST?
I was hoping that changing
connection.setRequestMethod("GET");
to
connection.setRequestMethod("POST");
would have done the trick, but the parameters are still sent via GET method.
Has HttpURLConnection got any method that would help?
Is there any helpful Java construct?
Any help would be very much appreciated.
In a GET request, the parameters are sent as part of the URL.
In a POST request, the parameters are sent as a body of the request, after the headers.
To do a POST with HttpURLConnection, you need to write the parameters to the connection after you have opened the connection.
This code should get you started:
String urlParameters = "param1=a&param2=b&param3=c";
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
int postDataLength = postData.length;
String request = "http://example.com/index.php";
URL url = new URL( request );
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setDoOutput( true );
conn.setInstanceFollowRedirects( false );
conn.setRequestMethod( "POST" );
conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty( "charset", "utf-8");
conn.setRequestProperty( "Content-Length", Integer.toString( postDataLength ));
conn.setUseCaches( false );
try( DataOutputStream wr = new DataOutputStream( conn.getOutputStream())) {
wr.write( postData );
}
Here is a simple example that submits a form then dumps the result page to System.out. Change the URL and the POST params as appropriate, of course:
import java.io.*;
import java.net.*;
import java.util.*;
class Test {
public static void main(String[] args) throws Exception {
URL url = new URL("http://example.net/new-message.php");
Map<String,Object> params = new LinkedHashMap<>();
params.put("name", "Freddie the Fish");
params.put("email", "fishie#seamail.example.com");
params.put("reply_to_thread", 10394);
params.put("message", "Shark attacks in Botany Bay have gotten out of control. We need more defensive dolphins to protect the schools here, but Mayor Porpoise is too busy stuffing his snout with lobsters. He's so shellfish.");
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
for (int c; (c = in.read()) >= 0;)
System.out.print((char)c);
}
}
If you want the result as a String instead of directly printed out do:
StringBuilder sb = new StringBuilder();
for (int c; (c = in.read()) >= 0;)
sb.append((char)c);
String response = sb.toString();
I couldn't get Alan's example to actually do the post, so I ended up with this:
String urlParameters = "param1=a&param2=b&param3=c";
URL url = new URL("http://example.com/index.php");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
writer.close();
reader.close();
I find HttpURLConnection really cumbersome to use. And you have to write a lot of boilerplate, error prone code. I needed a lightweight wrapper for my Android projects and came out with a library which you can use as well: DavidWebb.
The above example could be written like this:
Webb webb = Webb.create();
webb.post("http://example.com/index.php")
.param("param1", "a")
.param("param2", "b")
.param("param3", "c")
.ensureSuccess()
.asVoid();
You can find a list of alternative libraries on the link provided.
import java.net.*;
public class Demo{
public static void main(){
String data = "data=Hello+World!";
URL url = new URL("http://localhost:8084/WebListenerServer/webListener");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.getOutputStream().write(data.getBytes("UTF-8"));
con.getInputStream();
}
}
i have read above answers and have created a utility class to simplify HTTP request. i hope it will help you.
Method Call
// send params with Hash Map
HashMap<String, String> params = new HashMap<String, String>();
params.put("email","me#example.com");
params.put("password","12345");
//server url
String url = "http://www.example.com";
// static class "HttpUtility" with static method "newRequest(url,method,callback)"
HttpUtility.newRequest(url,HttpUtility.METHOD_POST,params, new HttpUtility.Callback() {
#Override
public void OnSuccess(String response) {
// on success
System.out.println("Server OnSuccess response="+response);
}
#Override
public void OnError(int status_code, String message) {
// on error
System.out.println("Server OnError status_code="+status_code+" message="+message);
}
});
Utility Class
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import static java.net.HttpURLConnection.HTTP_OK;
public class HttpUtility {
public static final int METHOD_GET = 0; // METHOD GET
public static final int METHOD_POST = 1; // METHOD POST
// Callback interface
public interface Callback {
// abstract methods
public void OnSuccess(String response);
public void OnError(int status_code, String message);
}
// static method
public static void newRequest(String web_url, int method, HashMap < String, String > params, Callback callback) {
// thread for handling async task
new Thread(new Runnable() {
#Override
public void run() {
try {
String url = web_url;
// write GET params,append with url
if (method == METHOD_GET && params != null) {
for (Map.Entry < String, String > item: params.entrySet()) {
String key = URLEncoder.encode(item.getKey(), "UTF-8");
String value = URLEncoder.encode(item.getValue(), "UTF-8");
if (!url.contains("?")) {
url += "?" + key + "=" + value;
} else {
url += "&" + key + "=" + value;
}
}
}
HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // handle url encoded form data
urlConnection.setRequestProperty("charset", "utf-8");
if (method == METHOD_GET) {
urlConnection.setRequestMethod("GET");
} else if (method == METHOD_POST) {
urlConnection.setDoOutput(true); // write POST params
urlConnection.setRequestMethod("POST");
}
//write POST data
if (method == METHOD_POST && params != null) {
StringBuilder postData = new StringBuilder();
for (Map.Entry < String, String > item: params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(item.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(item.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
urlConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
urlConnection.getOutputStream().write(postDataBytes);
}
// server response code
int responseCode = urlConnection.getResponseCode();
if (responseCode == HTTP_OK && callback != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
// callback success
callback.OnSuccess(response.toString());
reader.close(); // close BufferReader
} else if (callback != null) {
// callback error
callback.OnError(responseCode, urlConnection.getResponseMessage());
}
urlConnection.disconnect(); // disconnect connection
} catch (IOException e) {
e.printStackTrace();
if (callback != null) {
// callback error
callback.OnError(500, e.getLocalizedMessage());
}
}
}
}).start(); // start thread
}
}
I see some other answers have given the alternative, I personally think that intuitively you're doing the right thing ;). Sorry, at devoxx where several speakers have been ranting about this sort of thing.
That's why I personally use Apache's HTTPClient/HttpCore libraries to do this sort of work, I find their API to be easier to use than Java's native HTTP support. YMMV of course!
GET and POST method set like this... Two types for api calling 1)get() and 2) post() . get() method to get value from api json array to get value & post() method use in our data post in url and get response.
public class HttpClientForExample {
private final String USER_AGENT = "Mozilla/5.0";
public static void main(String[] args) throws Exception {
HttpClientExample http = new HttpClientExample();
System.out.println("Testing 1 - Send Http GET request");
http.sendGet();
System.out.println("\nTesting 2 - Send Http POST request");
http.sendPost();
}
// HTTP GET request
private void sendGet() throws Exception {
String url = "http://www.google.com/search?q=developer";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
// add request header
request.addHeader("User-Agent", USER_AGENT);
HttpResponse response = client.execute(request);
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " +
response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
}
// HTTP POST request
private void sendPost() throws Exception {
String url = "https://selfsolve.apple.com/wcResults.do";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
// add header
post.setHeader("User-Agent", USER_AGENT);
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("sn", "C02G8416DRJM"));
urlParameters.add(new BasicNameValuePair("cn", ""));
urlParameters.add(new BasicNameValuePair("locale", ""));
urlParameters.add(new BasicNameValuePair("caller", ""));
urlParameters.add(new BasicNameValuePair("num", "12345"));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
HttpResponse response = client.execute(post);
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + post.getEntity());
System.out.println("Response Code : " +
response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
}
}
I had the same issue. I wanted to send data via POST.
I used the following code:
URL url = new URL("http://example.com/getval.php");
Map<String,Object> params = new LinkedHashMap<>();
params.put("param1", param1);
params.put("param2", param2);
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
String urlParameters = postData.toString();
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
String result = "";
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
result += line;
}
writer.close();
reader.close()
System.out.println(result);
I used Jsoup for parse:
Document doc = Jsoup.parseBodyFragment(value);
Iterator<Element> opts = doc.select("option").iterator();
for (;opts.hasNext();) {
Element item = opts.next();
if (item.hasAttr("value")) {
System.out.println(item.attr("value"));
}
}
Try this pattern:
public static PricesResponse getResponse(EventRequestRaw request) {
// String urlParameters = "param1=a&param2=b&param3=c";
String urlParameters = Piping.serialize(request);
HttpURLConnection conn = RestClient.getPOSTConnection(endPoint, urlParameters);
PricesResponse response = null;
try {
// POST
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
// RESPONSE
BufferedReader reader = new BufferedReader(new InputStreamReader((conn.getInputStream()), StandardCharsets.UTF_8));
String json = Buffering.getString(reader);
response = (PricesResponse) Piping.deserialize(json, PricesResponse.class);
writer.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
conn.disconnect();
System.out.println("PricesClient: " + response.toString());
return response;
}
public static HttpURLConnection getPOSTConnection(String endPoint, String urlParameters) {
return RestClient.getConnection(endPoint, "POST", urlParameters);
}
public static HttpURLConnection getConnection(String endPoint, String method, String urlParameters) {
System.out.println("ENDPOINT " + endPoint + " METHOD " + method);
HttpURLConnection conn = null;
try {
URL url = new URL(endPoint);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(method);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "text/plain");
} catch (IOException e) {
e.printStackTrace();
}
return conn;
}
This answer covers the specific case of the POST Call using a Custom Java POJO.
Using maven dependency for Gson to serialize our Java Object to JSON.
Install Gson using the dependency below.
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<scope>compile</scope>
</dependency>
For those using gradle can use the below
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
}
Other imports used:
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.*;
import org.apache.http.impl.client.CloseableHttpClient;
import com.google.gson.Gson;
Now, we can go ahead and use the HttpPost provided by Apache
private CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("https://example.com");
Product product = new Product(); //custom java object to be posted as Request Body
Gson gson = new Gson();
String client = gson.toJson(product);
httppost.setEntity(new StringEntity(client, ContentType.APPLICATION_JSON));
httppost.setHeader("RANDOM-HEADER", "headervalue");
//Execute and get the response.
HttpResponse response = null;
try {
response = httpclient.execute(httppost);
} catch (IOException e) {
throw new InternalServerErrorException("Post fails");
}
Response.Status responseStatus = Response.Status.fromStatusCode(response.getStatusLine().getStatusCode());
return Response.status(responseStatus).build();
The above code will return with the response code received from the POST Call
here i sent jsonobject as parameter //jsonobject={"name":"lucifer","pass":"abc"}//serverUrl = "http://192.168.100.12/testing" //host=192.168.100.12
public static String getJson(String serverUrl,String host,String jsonobject){
StringBuilder sb = new StringBuilder();
String http = serverUrl;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(http);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setUseCaches(false);
urlConnection.setConnectTimeout(50000);
urlConnection.setReadTimeout(50000);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Host", host);
urlConnection.connect();
//You Can also Create JSONObject here
OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());
out.write(jsonobject);// here i sent the parameter
out.close();
int HttpResult = urlConnection.getResponseCode();
if (HttpResult == HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(
urlConnection.getInputStream(), "utf-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
Log.e("new Test", "" + sb.toString());
return sb.toString();
} else {
Log.e(" ", "" + urlConnection.getResponseMessage());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
return null;
}
Hello pls use this class to improve your post method
public static JSONObject doPostRequest(HashMap<String, String> data, String url) {
try {
RequestBody requestBody;
MultipartBuilder mBuilder = new MultipartBuilder().type(MultipartBuilder.FORM);
if (data != null) {
for (String key : data.keySet()) {
String value = data.get(key);
Utility.printLog("Key Values", key + "-----------------" + value);
mBuilder.addFormDataPart(key, value);
}
} else {
mBuilder.addFormDataPart("temp", "temp");
}
requestBody = mBuilder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
Utility.printLog("URL", url);
Utility.printLog("Response", responseBody);
return new JSONObject(responseBody);
} catch (UnknownHostException | UnsupportedEncodingException e) {
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("status","false");
jsonObject.put("message",e.getLocalizedMessage());
} catch (JSONException e1) {
e1.printStackTrace();
}
Log.e(TAG, "Error: " + e.getLocalizedMessage());
} catch (Exception e) {
e.printStackTrace();
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("status","false");
jsonObject.put("message",e.getLocalizedMessage());
} catch (JSONException e1) {
e1.printStackTrace();
}
Log.e(TAG, "Other Error: " + e.getLocalizedMessage());
}
return null;
}
I higly recomend http-request built on apache http api.
For your case you can see example:
private static final HttpRequest<String.class> HTTP_REQUEST =
HttpRequestBuilder.createPost("http://example.com/index.php", String.class)
.responseDeserializer(ResponseDeserializer.ignorableDeserializer())
.build();
public void sendRequest(String request){
String parameters = request.split("\\?")[1];
ResponseHandler<String> responseHandler =
HTTP_REQUEST.executeWithQuery(parameters);
System.out.println(responseHandler.getStatusCode());
System.out.println(responseHandler.get()); //prints response body
}
If you are not interested in the response body
private static final HttpRequest<?> HTTP_REQUEST =
HttpRequestBuilder.createPost("http://example.com/index.php").build();
public void sendRequest(String request){
ResponseHandler<String> responseHandler =
HTTP_REQUEST.executeWithQuery(parameters);
}
For general sending post request with http-request: Read the documentation and see my answers HTTP POST request with JSON String in JAVA, Sending HTTP POST Request In Java, HTTP POST using JSON in Java
I took Boann's answer and used it to create a more flexible query string builder that supports lists and arrays, just like php's http_build_query method:
public static byte[] httpBuildQueryString(Map<String, Object> postsData) throws UnsupportedEncodingException {
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : postsData.entrySet()) {
if (postData.length() != 0) postData.append('&');
Object value = param.getValue();
String key = param.getKey();
if(value instanceof Object[] || value instanceof List<?>)
{
int size = value instanceof Object[] ? ((Object[])value).length : ((List<?>)value).size();
for(int i = 0; i < size; i++)
{
Object val = value instanceof Object[] ? ((Object[])value)[i] : ((List<?>)value).get(i);
if(i>0) postData.append('&');
postData.append(URLEncoder.encode(key + "[" + i + "]", "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(val), "UTF-8"));
}
}
else
{
postData.append(URLEncoder.encode(key, "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(value), "UTF-8"));
}
}
return postData.toString().getBytes("UTF-8");
}
For those having trouble receiving the request on a php page using $_POST because you expect key-value pairs:
While all the answers where very helpful, I lacked some basic understanding on which string actually to post, since in the old apache HttpClient I used
new UrlEncodedFormEntity(nameValuePairs); (Java)
and then could use $_POST in php do get the key-value pairs.
To my understanding now one has build that string manually before posting. So the string needs to look like
val data = "key1=val1&key2=val2"
but instead just adding it to the url it is posted (in the header).
The alternative would be to use a json-string instead:
val data = "{\"key1\":\"val1\",\"key2\":\"val2\"}" // {"key1":"val1","key2":"val2"}
and pull it in php without $_POST:
$json_params = file_get_contents('php://input');
// echo_p("Data: $json_params");
$data = json_decode($json_params, true);
Here you find a sample code in Kotlin:
class TaskDownloadTest : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void): Void? {
var urlConnection: HttpURLConnection? = null
try {
val postData = JsonObject()
postData.addProperty("key1", "val1")
postData.addProperty("key2", "val2")
// reformat json to key1=value1&key2=value2
// keeping json because I may change the php part to interpret json requests, could be a HashMap instead
val keys = postData.keySet()
var request = ""
keys.forEach { key ->
// Log.i("data", key)
request += "$key=${postData.get(key)}&"
}
request = request.replace("\"", "").removeSuffix("&")
val requestLength = request.toByteArray().size
// Warning in Android 9 you need to add a line in the application part of the manifest: android:usesCleartextTraffic="true"
// https://stackoverflow.com/questions/45940861/android-8-cleartext-http-traffic-not-permitted
val url = URL("http://10.0.2.2/getdata.php")
urlConnection = url.openConnection() as HttpURLConnection
// urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") // apparently default
// Not sure what these are for, I do not use them
// urlConnection.setRequestProperty("Content-Type", "application/json")
// urlConnection.setRequestProperty("Key","Value")
urlConnection.readTimeout = 5000
urlConnection.connectTimeout = 5000
urlConnection.requestMethod = "POST"
urlConnection.doOutput = true
// urlConnection.doInput = true
urlConnection.useCaches = false
urlConnection.setFixedLengthStreamingMode(requestLength)
// urlConnection.setChunkedStreamingMode(0) // if you do not want to handle request length which is fine for small requests
val out = urlConnection.outputStream
val writer = BufferedWriter(
OutputStreamWriter(
out, "UTF-8"
)
)
writer.write(request)
// writer.write("{\"key1\":\"val1\",\"key2\":\"val2\"}") // {"key1":"val1","key2":"val2"} JsonFormat or just postData.toString() for $json_params=file_get_contents('php://input'); json_decode($json_params, true); in php
// writer.write("key1=val1&key2=val2") // key=value format for $_POST in php
writer.flush()
writer.close()
out.close()
val code = urlConnection.responseCode
if (code != 200) {
throw IOException("Invalid response from server: $code")
}
val rd = BufferedReader(
InputStreamReader(
urlConnection.inputStream
)
)
var line = rd.readLine()
while (line != null) {
Log.i("data", line)
line = rd.readLine()
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
urlConnection?.disconnect()
}
return null
}
}
Now I had to do an HTTP request class, it is probably not the most efficient class, but it works.
I collected some codes from this page and made it more dynamic.
Anyone who needs a complete code, I attached it below.
For an example of how to use it, you can look at the main method.
Also, if you are willing to improve classes online, you are more than welcome to help me make this class better.
import java.net.*;
import java.util.*;
import java.nio.charset.*;
import java.io.*;
public class HttpRequest {
String result = "";
HttpRequest(String _url, String _method, Map<String, String> _postData, String _contentType) {
try {
URL url = new URL( _url );
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection)con;
http.setRequestMethod(_method); // PUT is another valid option
http.setDoOutput(true);
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : _postData.entrySet())
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + entry.getValue());
//sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue()));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", _contentType);
http.setRequestProperty( "charset", "utf-8");
http.setRequestProperty( "Content-Length", Integer.toString( length ));
http.setInstanceFollowRedirects( false );
http.setUseCaches( false );
http.connect();
try(OutputStream os = http.getOutputStream()) {
os.write(out);
}
if (http.getResponseCode() == HttpURLConnection.HTTP_OK) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(http.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
result = result + line;
}
}
} else {
System.out.println("Bad response!");
}
}catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
}
HttpRequest(String _url, String _method, Map<String, String> _postData) {
this(_url, _method, _postData, "text/html");
}
HttpRequest(String _url, String _method) {
this(_url, _method, new HashMap<String, String>());
}
HttpRequest(String _url) {
this(_url, "GET");
}
public String toString() {
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<String, String> postData = new HashMap<String, String>();
postData.putIfAbsent("email", "test#test.com");
postData.putIfAbsent("password", "test");
HttpRequest result = new HttpRequest("https://httpbin.org/anything", "POST", postData, "application/x-www-form-urlencoded");
System.out.println(result.toString());
}
}
Appears that you also have to callconnection.getOutputStream() "at least once" (as well as setDoOutput(true)) for it to treat it as a POST.
So the minimum required code is:
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//connection.setRequestMethod("POST"); this doesn't seem to do anything at all..so not useful
connection.setDoOutput(true); // set it to POST...not enough by itself however, also need the getOutputStream call...
connection.connect();
connection.getOutputStream().close();
You can even use "GET" style parameters in the urlString, surprisingly. Though that might confuse things.
You can also use NameValuePair apparently.

Send image from Android client to AppEngine Cloud Endpoint

I am developing an Android applicaiton with AppEngine backend. I am creating the server part with Google Cloud Endpoints in Java. My problem is that I cannot send a Bitmap from the client to the server.
I used the answer from this question but even if the client part does not seem to have any problems at all, the server part does not receive the data at all. I also think this solution might be a bit complicated and that it might work a different, easier way, however this is my first time implementing a server and first time sending a picture to it so I accept any good tips on this. Thanks!
Here is my code:
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
String charset = "UTF-8";
HttpURLConnection connection = (HttpURLConnection) new URL("https://path_to_my_app/_ah/api/registration/v1/uploadImage").openConnection();
connection.setDoOutput(true);
connection.setReadTimeout(60000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
OutputStream output = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!
// Send text file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + somename + "\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF).flush();
BufferedReader reader = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byteArray = stream.toByteArray();
try {
reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(byteArray), charset));
for (String line; (line = reader.readLine()) != null;) {
writer.append(line).append(CRLF);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
writer.flush();
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF);
}
finally
{
if (writer != null)
{
writer.close();
}
}
The server part:
#ApiMethod(name = "uploadImage", httpMethod = "POST")
public void uploadImage(HttpServletRequest request, HttpServletResponse response) throws IOException
{
ServletFileUpload fileUpload = new ServletFileUpload();
try
{
FileItemIterator iterator = fileUpload.getItemIterator(request);
while(iterator.hasNext()){
FileItemStream itemStream = iterator.next();
String fieldName = itemStream.getFieldName();
log.info("field name:"+fieldName);
InputStream stream = itemStream.openStream();
String result = getStringFromInputStream(stream);
log.info("result: "+result);
stream.close();
}
}
catch (FileUploadException e)
{
e.printStackTrace();
}
}
I am getting 204 no Content type now.
I did it!
I think this is not the best way of doing it but it´s working so I am fine until I get a better solution.
So I take the Bitmap image and convert it to String:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byte[] bitmapByte = outputStream.toByteArray();
String stringEncodedImage = Base64.encodeToString(bitmapByte, Base64.DEFAULT);
Then I create a httpPostRequest and set a JsonObject to it with the image converted to String in it.
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://my_app_path/_ah/api/registration/v1/uploadImage");
JSONObject jsonObject = new JSONObject();
jsonObject.put("image",stringEncodedImage);
StringEntity stringEntity = new StringEntity(jsonObject.toString());
httpPost.addHeader("Content-Type", "application/json");
httpPost.setEntity(stringEntity);
HttpResponse response = httpClient.execute(httpPost);
On the server side, in my Endpoint, I do this:
#ApiMethod(name = "uploadImage", httpMethod = "POST")
public JSONObject uploadImage(JSONObject request) throws IOException
{
String imageInString = (String) request.get("image");
Blob blob = new Blob(imageInString.getBytes());
....save blob and do whatever you want...
}
The same goes the other way. I pack Blob into JsonObject and send it over.

httpsurlconnection posts string wrongly in java application

In my java application I used a Httpsurlconnection to post some string data to the server. When I test this code on android, it works perfectly. However, in a java application it does not work. Client java application is as follows:
public static void main(String[] args) {
disableSslVerification();
new HttpsClient().testIt();
}
private void testIt() {
String https_url = "https://XXX.XX.XXX.XXX:XXXX/XXXXX/TestServlet";
URL url;
try {
url = new URL(https_url);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
print_content(con, "test");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void print_content(HttpsURLConnection connection, String data) {
if (connection != null) {
try {
connection.setConnectTimeout(6000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
Charset cSet = Charset.forName("UTF-8");
byte bytes[] = data.getBytes(cSet);
connection.setRequestProperty("Content-Length", ""
+ Integer.toString(bytes.length));
connection.setRequestProperty("Content-Language", "tr");
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(
connection.getOutputStream());
wr.write(bytes);
wr.flush();
wr.close();
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is, cSet));
String line;
StringBuilder response = new StringBuilder();
while ((line = rd.readLine()) != null) {
response.append(line);
response.append(System.getProperty("line.separator"));
}
rd.close();
System.out.println(response.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
And the servlet is as follows:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String s = getHTML(request);
try {
out.print("received data:");
out.print(s);
} finally {
out.close();
}
}
private String getHTML(HttpServletRequest request) throws IOException {
int n = request.getContentLength();
if (n < 1) {
return "";
}
byte bytes[] = new byte[n];
request.getInputStream().read(bytes);
return new String(bytes, "UTF-8");
}
When I run this application, servlet's response is:
received data:t☐☐☐
Always only the first character is correctly send to the servlet. The same code works perfect on android. Can anyone help me please? Thanks...
I can't see an obvious problem with your code that would cause this.
Can anyone help me please?
I suggest that you take a methodical approach to investigating the problem. Use a packet sniffer to check what is actually being sent over the wire. Check that the actual headers in the request and response are correct. Check that the request and response bodies are really properly encoded UTF-8 ...
What you find in your investigation / evidence gathering will help you figure out where the problem (or problems) are occurring ... and that will allow you to home in on the part(s) of your code that is/are responsible.
request.getInputStream().read(bytes);
You might need to do this read in a loop. At the very least, check how many bytes have been read. The array appears to be empty except for the first char.
Reads some number of bytes from the input stream and stores them into
the buffer array b. The number of bytes actually read is returned as
an integer. This method blocks until input data is available, end of
file is detected, or an exception is thrown.

How to setEntity on a HttpURLConnection

In my project I must strictly use HttpURLConnection class
I have this following code which I got from the internet
MultipartEntity multiPart = new MultiPartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null Chartset.forName("UTF-8");
File f = new File("/home/abhishek/foo.docx");
FileBody fb = new FileBody(f);
multiPart.addPart("file", fb);
HttpPost post = new HttpPost();
post.setHeader("ENCTYPE", "multipart/form-data");
post.setEntity(multiPart);
Problem is that I cannot use HttpPost ... In my project only HttpURLConnection class works!
So I need to translate the code above into HttpURLConnection.
I cannot find anything similar to setEntity on the HttpUrlConnection.
Edit::
Based on the suggestions below. I have this code
public class RESTFileUpload {
public static void main(String[] args) throws Exception {
Authenticator.setDefault(new Authenticator() {
#Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("domain\\user", "Password".toCharArray());
}
});
String filePath = "/home/abhishek/Documents/HelloWorld.docx";
String fileName = "HelloWorld.docx";
String fileNameShort = "HelloWorld";
String urlStr = "https://sp.company.com/sites/abhi_test/_vti_bin/listdata.svc/SharedDocuments/RootFolder/Files/add(url=#TargetFileName,overwrite='true')&#TargetFileName=" + fileName;
String crlf = "\r\n";
String twoHypens = "--";
String boundary = "*****";
URL url = new URL(urlStr);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestMethod("POST");
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Cache-Control", "no-cache");
con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream request = new DataOutputStream(con.getOutputStream());
request.writeBytes(twoHypens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data;name=\"" + fileNameShort + "\";fileName=\"" + fileName + "\"" + crlf);
request.writeBytes(crlf);
request.write(convertToByteArray(filePath));
request.writeBytes(crlf);
request.writeBytes(twoHypens + boundary + twoHypens + crlf);
request.flush();
request.close();
InputStream responseStream = new BufferedInputStream(con.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder strBuilder = new StringBuilder();
while((line = responseStreamReader.readLine()) != null) {
strBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = strBuilder.toString();
responseStream.close();
con.disconnect();
System.out.println(response);
}
private static byte[] convertToByteArray(String filePath) {
File f = new File(filePath);
byte[] retVal = new byte[(int)f.length()];
try {
FileInputStream fis = new FileInputStream(f);
fis.read(retVal);
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch(IOException ex2) {
ex2.printStackTrace();
}
return retVal;
}
}
But I get the error
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: https://sp.web.gs.com/sites/abhi_test/_vti_bin/listdata.svc/SharedDocuments/
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at RESTFileUpload.main(RESTFileUpload.java:62)
HttpURLConnection has .getInputStream() and .getOutputStream() methods. If you wish to send body content with an Http request, you call .setDoOutput(true) on your HttpURLConnection object, call .getOutputStream() to get an Output stream and then write the content of your entity to the output stream (either as raw bytes, or using a Writer implementation of some sort), closing it when you are finished writing.
For more details, see the API docs for HttpURLConnection here.
To post files using the HttpURLConnection you have to compose the file wrapper manually. Take a look at this answer, it should be helpful for you.

Categories

Resources