DataOutputStream seems not send parameters - java

I trying to send POST data with DataOutputStream and get response data.
I coded like this.
String urlParameters = "table=page&format=xml";
out.println(urlParameters+"<br/><br/><br/>");
String searchUrl = "http://localhost:8081/WebTest/test.jsp";
URL url = new URL(searchUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("charset", "utf-8");
connection.setRequestProperty("Content-Length", ""+Integer.toString(urlParameters.getBytes().length));
connection.setUseCaches (false);
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeUTF(urlParameters);
wr.flush();
wr.close();
if( connection.getResponseCode() == 200){
XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
XMLStreamReader reader = xmlFactory.createXMLStreamReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
try{
while (reader.hasNext()) {
Integer eventType = reader.next();
if (eventType.equals(XMLStreamReader.START_ELEMENT)){
out.print(" " + reader.getName() + "<br/>");
}else if (eventType.equals(XMLStreamReader.CHARACTERS)){
out.print(" " + reader.getText() + "<br/>");
}else if (eventType.equals(XMLStreamReader.ATTRIBUTE)){
out.print(" " + reader.getName() + " <br/>");
}else if (eventType.equals(XMLStreamReader.END_ELEMENT)){
out.print(" " + reader.getName() + " <br/>");
}
}
} catch (XMLStreamException e){
e.printStackTrace();
} finally{
connection.disconnect();
reader.close();
}
}
and this is test.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<%# page language="java" contentType="text/xml; charset=UTF-8" %>
<response>
<table><%=request.getParameter("table") %></table>
</response>
But, result was
response
table
null
table
response
Why request.getParameter("table") cannot get (or DataOutputStream doesn't send) data?
I'm so confused.
Thanks everyone's help.

You should not use DataOutputStream.writeUTF, see API
First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for the character. If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.
That is, what DataOutputStream.writeUTF writes can be read only with DataInputStream.readUTF
I suggest to use
OutputStreamWriter w = new OutputStreamWriter(connection.getOuputStream(), "UTF-8");
w.write(urlParameters);
w.flush();

Related

How to create a http response for images in java?

I have been trying to create a simple java web server everything works fine for files such as html or css but I'm unable to send image responses correctly. The problem is obviously with the image data that I'm sending but I'm not sure how to do it properly. I have been searching for any information about it for a long time not and I just can't find anything useful that would fix my problem.
Part of my code:
public void Send(String path) throws IOException {
File file = new File(path);
if(file.exists()) {
if(!file.isDirectory()) {
if(isImage(file)) {
InputStream is = new FileInputStream(file);
byte[] bytes = IOUtils.toByteArray(is);
String response = "HTTP/1.1 200 OK" + CRLF + "Content-Length: " + bytes.length + CRLF;
response += "content-type: image/jpeg" + CRLF + CRLF;
outputStream.write(response.getBytes());
outputStream.write(bytes);
outputStream.write((CRLF + CRLF).getBytes());
outputStream.flush();
} else {
String data = "";
BufferedReader br = new BufferedReader(new FileReader(file));
String st;
while ((st = br.readLine()) != null) {
data += st;
}
int length = data.getBytes().length;
String response = "HTTP/1.1 200 OK" + CRLF + "Content-Length: " + length + CRLF;
response += CRLF + data + CRLF + CRLF;
br.close();
outputStream.write(response.getBytes());
}
return;
}
}
SendError("404 Not Found");
}
outputStream is OutputStream from a Socket.
I saw this but I think I'm only using streams at least for the image part.
I'm new to this so any help would be appreciated!
EDIT (more inforamtion):
Browser information:
Headers
Preview
The isImage(file) methode works fine I have tested it but here it is:
private boolean isImage(File file) {
String mimetype = new MimetypesFileTypeMap().getContentType(file);
String type = mimetype.split("/")[0];
return type.equals("image");
}
And the image is 2.jpg
EDIT 2
I wrote this code to write the content of the array in a text file:
String out = "";
for(int i = 0; i < bytes.length; i++) {
if(i%16 == 0) {
out += "\n";
}
out += String.format("%02X ", bytes[i]);
}
BufferedWriter writer = new BufferedWriter(new FileWriter("test.txt"));
writer.write(out);
writer.close();
So I checked the start of both the image and the array and they seem to be identical.
Start of the image data
Start if the array
After that I tried to create a client for testing:
private static void Get2(String link) throws IOException {
URL url = new URL(link);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Connection", "keep-alive");
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.68");
con.setRequestProperty("Accept", "image/webp,image/apng,image/*,*/*;q=0.8");
con.setRequestProperty("Sec-Fetch-Site", "same-origin");
con.setRequestProperty("Sec-Fetch-Mode", "no-cors");
con.setRequestProperty("Sec-Fetch-Dest", "image");
con.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
con.setRequestProperty("Accept-Language", "sl,en;q=0.9,en-GB;q=0.8,en-US;q=0.7");
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
con.setInstanceFollowRedirects(false);
int status = con.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
int i = 0;
while ((inputLine = in.readLine()) != null) {
if(i < 5) {
System.out.println(inputLine);
} else {
content.append(inputLine);
}
i++;
}
in.close();
con.disconnect();
BufferedWriter writer = new BufferedWriter(new FileWriter("test2.txt"));
writer.write(content.toString());
writer.close();
}
I called the function: Get2("http://localhost:8080/images/2.jpg");
And got saved data in the test2.txt. Inside I saw some parts of similar data but it's clearly something wrong with it. I'm not sure if I'm using this client test wrong so if I'm doing something wrong or should be using something else let me know.
Image (left test2.txt, right test.txt)
Thanks to everyone that will and already helped or had any suggestions.
I finally figured it out. Actually my bad for not providing everything.
String CRLF = "\n\r";
But apparently, it should only be \n.
I read somewhere that windows automatically adds \r after \n. I don't know if that's true but removing \r fixed my problem as before I had 2 empty lines right after GET / HTTP/1.1 so the other content was considered as part of the data.
As soon as I changed that everything worked fine.
Again thanks for your help!
EDIT
Nevermind. What I did wrong was the order of \n and \r. It should be \r\n not \n\r

EDIT: How do I send this post Request with parameters AND form-data like this postman screenshot in JAVA?

I'm trying to send a POST request to grab comments but it doesn't work in Java while it does work with postman.
I get an 403 Forbidden error, but on postman it retrieves the data i need just fine..
Here's the Java code I'm trying to use to replicate the behavior.
String targetUrl = YOUTBE_COMMENTS_AJAX_URL;
String urlParameters = "action_load_comments=1&order_by_time=True&filter=jBjXVrS8nXs";
String updatedURL = targetUrl + "?" + urlParameters;
URL url = null;
InputStream stream = null;
HttpURLConnection urlConnection = null;
try {
url = new URL(updatedURL);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("content-type", "multipart/form-data");
urlConnection.setRequestProperty("user-agent", "USER_AGENT");
urlConnection.setDoOutput(true);
String data = URLEncoder.encode("video_id", "UTF-8")
+ "=" + URLEncoder.encode(youtubeId, "UTF-8");
data += "&" + URLEncoder.encode("session_token", "UTF-8") + "="
+ URLEncoder.encode(xsrfToken, "UTF-8");
data += "&" + URLEncoder.encode("page_token", "UTF-8") + "="
+ URLEncoder.encode(pageToken, "UTF-8");
urlConnection.connect();
OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
wr.write(data);
wr.flush();
stream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"), 8);
String result = reader.readLine();
return result;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
Here's an example of what postman is sending in their headers
It seems like your problem is here (see inline comments):
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(urlParameters);
// you wrote your URL parameters into Body
wr.flush();
wr.close();
//You closed your body and told server - you are done with request
conn.getOutputStream().write(postDataBytes);
// you wrote data into closed stream - server does not care about it anymore.
You have to append your urlParameters directly to the URL when you open it
Then you have to write your Form Data into body as you do:
conn.getOutputStream().write(postDataBytes);
and then close output stream

Sending Arabic over HTTP post as parameter not working [duplicate]

This question already has answers here:
How to handle Arabic in java
(2 answers)
Closed 6 years ago.
I hit a URL with an Arabic parameter value (like below):
http://62.215.226.164/fccsms_P.aspx?UID=something&P=somethingS=InfoText&G=96567771404&M=اخص شقث غخع خن ؤخةث&L=E
It works perfectly; I get the message on a phone in Arabic. When I try to achieve the same through the following code, though, I only get question marks in the message.
public void sendSms(SendSms object)
throws MalformedURLException, ProtocolException, IOException
{
String message = new String(object.getMessage().getBytes(), "UTF-8");
System.out.println(message); // This also prints only question marks
PrintStream out = new PrintStream(System.out, true, "UTF-8");
out.print(message);
String charset="UTF-8";
URL url = new URL("http://62.215.226.164/fccsms_P.aspx");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Accept-Charset", charset);
con.setRequestMethod("POST");
// con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en,ar_KW;q=0.5");
con.setRequestProperty("Content-Type", "text/html;charset=utf-8");
String urlParameters = "UID=test&P=test&S=InfoText&G=965" + object.getPhone() + "&M= Hello " + object.getName() + " " + message + " &L=A";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
}
To get the message in Arabic, what do I need to add or change in the code?
If you want to send Arabic data as parameter you need to encode this data to UTF-8.
You can use following code to get the proper output.
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
bw.write(urlParameters);
bw.flush();
bw.close();
The problem occurred in the following code. So replace your code below with the code above.
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
It is because http doesn't support the characterset,
your browser handles url-encoding automatically,
In your code you need to encode each parameter separately because of special characters eg. asuming object.getMessage() does not return ???:
String message = URLEncoder.encode(
""اخص شقث غخع خن ؤخةث",
java.nio.charset.StandardCharsets.UTF_8.toString() );
And then concatenate:
String urlParameters = "UID=...&M=" + message + "&L=A";

Java Applet 411 Content Length

I am new to Java. I wrote an applet with a gui that sends results (int w and int p) to a server, and I get the "411 Length Required" error. What am I doing wrong? How do you set a Content-Length?
This is the method that communicates with the server:
public void sendPoints1(int w, int p){
try {
String url = "http://somename.com:309/api/Results";
String charset = "UTF-8";
String query = String.format("?key=%s&value=%s",
URLEncoder.encode(String.valueOf(w), charset),
URLEncoder.encode(String.valueOf(p), charset));
String length = String.valueOf((url + query).getBytes("UTF-8").length);
HttpURLConnection connection = (HttpURLConnection) new URL(url + query).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", length);
connection.connect();
System.out.println("Responce Code: " + connection.getResponseCode());
System.out.println("Responce Message: " + connection.getResponseMessage());
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
I'm not 100% sure why you're getting a 411 error code, but it probably has to do with the fact that you are not sending any content with your POST. The content-length header should be the length in bytes of the body of the request. You are setting it to the length of the url!
Either change the request to a GET or put the query into the body of the request instead of into the url itself. If you do the latter, set the content-length to the length of the body only.
public void sendPoints1(int w, int p){
try {
String url = "http://somename.com:309/api/Results";
String charset = "UTF-8";
String query = String.format("key=%s&value=%s",
URLEncoder.encode(String.valueOf(w), charset),
URLEncoder.encode(String.valueOf(p), charset));
byte[] queryBytes = query.getBytes("UTF-8");
String length = String.valueOf((url + query).getBytes("UTF-8").length);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", length);
OutputStream os = connection.getOutputStream();
os.write(queryBytes);
os.flush();
connection.connect();
System.out.println("Responce Code: " + connection.getResponseCode());
System.out.println("Responce Message: " + connection.getResponseMessage());
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
Request uri includes query , can use GET method.
connection.setRequestMethod("POST"); // modify to GET
connection.setRequestProperty("Content-Length", length); //remove the line
if use POST method, include 'content-length' heade, must send data.
for example:
public void sendPoints1(int w, int p){
try {
String url = "http://somename.com:309/api/Results";
//value type is int ,don't need URLEncoder.
byte[] data = ("key="+w+"&value="+p).getBytes("UTF-8");
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", data.length);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //URLencode...
OuptputStream out = connection.getOutputStream();
out.write(data);
out.flush();
InputStream in = connnection.getInputStream();
//read .....
System.out.println("Responce Code: " + connection.getResponseCode());
System.out.println("Responce Message: " + connection.getResponseMessage());
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
Since all information is passed as query string which is a part of URL, you need not setRequestMethod as POST. But if you still want to set it to POST as part of your logic, then setRequestProperty("Content-Length", "0") as Http Server expect Length to be read when POST method is called. In your case nothing is written as POST information so better set it to ZERO, even thought default value is ZERO at times server may give response errorCode as 411, response Message: Required Length

Image writing over URLConnection

I am trying to write an image over an HttpURLConnection.
I know how to write text but I am having real problems trying
to write an image
I have succeeded in writing to the local HD using ImageIO:
But I am trying to write Image by ImageIO on url and failed
URL url = new URL(uploadURL);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "multipart/form-data;
boundary=" + boundary);
output = new DataOutputStream(connection.getOutputStream());
output.writeBytes("--" + boundary + "\r\n");
output.writeBytes("Content-Disposition: form-data; name=\"" + FIELD_NAME + "\";
filename=\"" + fileName + "\"\r\n");
output.writeBytes("Content-Type: " + dataMimeType + "\r\n");
output.writeBytes("Content-Transfer-Encoding: binary\r\n\r\n");
ImageIO.write(image, imageType, output);
the uploadURL is the url to an asp page on the server which will upload the image with the file name given in "content-Disposition: part.
now when I send this then asp page find the request and find the name of file. but does not find the file to be uploaded.
The problem is that when writing by ImageIO on URL what will the name of the file on which the ImageIO is writing,
So please help me how ImageIO will write an image on URLConnection and how can I know the name of the file which I have to use in the asp page to upload the file
Thanks for taking the time to read this post
Dilip Agarwal
First I believe that you should call io.flush() and then io.close() after writing image.
Second content type seems strange for me. It seems that you are trying to submit form while it is actually image. I do not know what does your asp expect but typically when I write code that should transfer file over HTTP I send appropriate content type, e.g. image/jpeg.
Here is for example code snippet I extracted from one small utility that I wrote and I am using during my current work:
URL url = new URL("http://localhost:8080/handler");
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "image/jpeg");
con.setRequestMethod("POST");
InputStream in = new FileInputStream("c:/temp/poc/img/mytest2.jpg");
OutputStream out = con.getOutputStream();
copy(in, con.getOutputStream());
out.flush();
out.close();
BufferedReader r = new BufferedReader(new InputStreamReader(con.getInputStream()));
// obviously it is not required to print the response. But you have
// to call con.getInputStream(). The connection is really established only
// when getInputStream() is called.
System.out.println("Output:");
for (String line = r.readLine(); line != null; line = r.readLine()) {
System.out.println(line);
}
I used here method copy() that I took from Jakarta IO utils. Here is the code for reference:
protected static long copy(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[12288]; // 12K
long count = 0L;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
Obviously the server side must be ready to read the image content directly from POST body.
I hope this helps.
The OP seems lost into oblivion but for the benefit of Mister Kite :
// main method
URL url = new URL(uploadURL);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true); // triggers "POST"
// connection.setDoInput(true); // only if needed
connection.setUseCaches(false); // dunno
final String boundary = Long.toHexString(System.currentTimeMillis());
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
+ boundary);
output = new DataOutputStream(connection.getOutputStream());
try {
// image must be a File instance
flushMultiPartData(image, output, boundary);
} catch (IOException e) {
System.out.println("IOException in flushMultiPartData : " + e);
return;
}
// ...
private void flushMultiPartData(File file, OutputStream serverOutputStream,
String boundary) throws FileNotFoundException, IOException {
// SEE https://stackoverflow.com/a/2793153/281545
PrintWriter writer = null;
try {
// true = autoFlush, important!
writer = new PrintWriter(new OutputStreamWriter(serverOutputStream,
charsetForMultipartHeaders), true);
appendBinary(file, boundary, writer, serverOutputStream);
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF);
} finally {
if (writer != null) writer.close();
}
}
private void appendBinary(File file, String boundary, PrintWriter writer,
OutputStream output) throws FileNotFoundException, IOException {
// Send binary file.
writer.append("--" + boundary).append(CRLF);
writer.append(
"Content-Disposition: form-data; name=\"binaryFile\"; filename=\""
+ file.getName() + "\"").append(CRLF);
writer.append("Content-Type: "
+ URLConnection.guessContentTypeFromName(file.getName()))
.append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
InputStream input = null;
try {
input = new FileInputStream(file);
byte[] buffer = new byte[1024];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
output.flush(); // Important! Output cannot be closed. Close of
// writer will close output as well.
} finally {
if (input != null) try {
input.close();
} catch (IOException logOrIgnore) {}
}
writer.append(CRLF).flush(); // CRLF is important! It indicates end of
// binary boundary.
}
You may want to add Gzip compression - see file corrupted when I post it to the servlet using GZIPOutputStream for a working class with or without Gzip. The ImageIO has no place here - just write the bytes past the wire and use ImageIO to your heart's content on the server. Based on #BalusC answer

Categories