URL parameter encoding/receiving problem - java

I use the below code to send data to a servlet:
When encoding = "UTF-8" or "GBK", the data is received correctly.
But when encoding = "UTF-16", The receiver receives null. WHY??
The Sender:
URL url = new URL(notifyURL);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=" + encoding);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write("notify_id=" + URLEncoder.encode("123", encoding) + "&notify_type=" + URLEncoder.encode("any", encoding));
out.flush();
out.close();
connection.connect();
The receiver servlet:
log.info(request.getParameter("notify_type")); //print null

According to the Javadocs for URLEncoder, you should only use UTF-8 because other encodings may cause problems. They link directly to the W3C spec from the Javadocs.

You have 2 issues,
UTF-16 is not supported by lots of web servers. Some URLDecoder can only handle single byte encoding (ASCII, Latin-1) and UTF-8.
You are using mixed encoding if your default encoding is not UTF-16. UTF-8 and GBK are both ASCII compatible (ASCII is encoded as itself) so you can mix with ASCII but you can't do that with UTF-16.

Related

(spring boot or java) I have a problem opening URL PDF

spring boot or java read/open pdf url and ResponseEntity attachment file .pdf
Call the URL https://xxxxx.xxx/file.pdf
Read the file from step 1 and display it. By setting the response value as follows:
Content-Type : application/pdf
Content-Transfer-Encoding : binary
Content-disposition : attachment; filename=filename.pdf
Content-Length : xxxx
URL url = new URL(apiReportDomain
+ "/rest_v2/reports/reports/cms/loan_emergency/v1_0/RTP0003_02.pdf?i_ref_code=" + documentId);
System.out.println(url);
String encoding = Base64.getEncoder().encodeToString(
(apiReportUsername + ":" + apiReportPassword).getBytes(StandardCharsets.UTF_8));
HttpURLConnection connectionApi = (HttpURLConnection) url.openConnection();
connectionApi.setRequestMethod("GET");
connectionApi.setDoOutput(true);
connectionApi.setRequestProperty("Authorization", "Basic " + encoding);
connectionApi.setRequestProperty("Content-Type", "application/pdf");
InputStream content = connectionApi.getInputStream();
BufferedReader in = new BufferedReader(
new InputStreamReader(content));
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = in.read()) != -1) {
sb.append((char) cp);
}
byte[] output = sb.toString().getBytes();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("charset", "utf-8");
responseHeaders.setContentType(MediaType.valueOf("application/pdf"));
responseHeaders.setContentLength(output.length);
responseHeaders.set("Content-disposition", "attachment; filename=filename.pdf");
return new ResponseEntity<byte[]>(output, responseHeaders, HttpStatus.OK);
enter image description here
which the result i got is a blank page But in fact, this PDF contains a full sheet of text.
Update this if it does or does not operate, I think the problem would be the https and certificate verification at client download by your original connection.
You need the certificate to decrypt the pdf and formally accept the certificate. See JCA cryptography API.
Also the following is best MIME type for sending binary download.
Content-Type : application/octet-stream
https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/HttpsURLConnection.html
The issue is that the server needs to fetch the file from the internet, and then pass it on. Except of a redirect (which would look like cross-site traffic).
First write local code to fetch the PDF in a local test application.
It could be that you need to use java SE HttpClient.
It just might be you need to fake a browser as agent, and accept cookies, follow a redirect. That all can be tested by a browser's development page looking at the network traffic in detail.
Then test that you can store a file with the PDF response.
And finally wire the code in the spring application, which is very similar on yielding the response. You could start with a dummy response, just writing some hard-coded bytes.
After info in the question
You go wrong in two points:
PDFs are binary data, String is Unicode, with per char 2 bytes, requiring a conversion back and forth: the data will be corrupted and the memory usage twice, and it will be slow.
String.getBytes(Charset) and new String(byte[], Charset) prevent that the default Charset of the executing PC is used.
Keeping the PDF first entirely in memory is not needed. But then you are missing the Content-Length header.
InputStream content = connectionApi.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
content.transferTo(baos);
byte[] output = baos.toByteArray();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("charset", "utf-8");
responseHeaders.setContentType(MediaType.valueOf("application/pdf"));
responseHeaders.setContentLength(output.length);
responseHeaders.set("Content-disposition",
"attachment; filename=filename.pdf");

How to set character encoding in SOAP request

I am calling a SAP SOAP Service from a web servlet in Java. For some reason SAP is giving me an error every time I use special characters in the fields of my request such as 'è' or 'à'. The WSDL of the SOAP Service is defined in UTF-8 and I have set my character encoding accordingly as you can see below. However I am not sure this is the correct way. Also, notice that if I use SOAP UI (with the same envelope) the request works correctly so it must be something on Java side.
URL url = new URL(SOAP_URL);
String authorization = Base64Coder.encodeString(SOAP_USERNAME + ":" + SOAP_PASSWORD);
String envelope = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:urn='urn:sap-com:document:sap:soap:functions:mc-style'><soapenv:Header/><soapenv:Body><urn:ZwsMaintainTkt><item>à</item></urn:ZwsMaintainTkt></soapenv:Body></soapenv:Envelope>";
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(SOAP_TIMEOUT);
con.setRequestMethod("POST");
con.setRequestProperty("Content-type", "text/xml; charset=utf-8");
con.setRequestProperty("SOAPAction", SOAP_ACTION_ZWSMANTAINTKT);
con.setRequestProperty("Authorization", "Basic " + authorization);
con.setDoOutput(true);
con.setDoInput(true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(con.getOutputStream());
outputStreamWriter.write(envelope);
outputStreamWriter.close();
InputStream inputStream = con.getInputStream();
Since a soap-request is xml use the xml-header to specify the encoding of your request:
<?xml version="1.0" encoding="UTF-8"?>
new OutputStreamWriter(con.getOutputStream()) uses the platform-default encoding which most probably is some flavour of ISO8859. Use new OutputStreamWriter(con.getOutputStream(),"UTF-8") instead

How can I set the encoding of a httpExchange response?

I'm trying to modify some server code which uses an httpExchangeobject to handle the server's response to the client.
My issue is that for responses containing characters not supported by iso-8859-1, such as Chinese characters, I get something like '????' in place of the characters. I'd like to set the encoding of the response to utf-8, but have thus far been unsuccessful in doing so.
I tried adding this line:
httpExchange.getResponseHeaders().put("charset", Arrays.asList("UTF-8"));
This successfully puts a "charset" header in the response, but I still can't send the characters I want in the response.
How do I set the encoding of the response to allow for these characters?
Use Content-Type header to specify encoding.
String encoding = "UTF-8";
httpExchange.getResponseHeaders().set("Content-Type", "text/html; charset=" + encoding);
Writer out = new OutputStreamWriter(httpExchange.getResponseBody(), encoding));
out.write(something);

new to android - understanding the use of OutputStreamWriter in web service calls

I have been going over the following tutorial and came across this code which I do not understand the purpose of:
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write( data );
wr.flush();
I don't know what is the purpose of the above code and where is it writing this data to...
From what I could gather, the documentation states that it converts character to bytes... but then it writes it to some where... not sure why this is.
It is basically used for turning a character stream into a byte stream.
The byte streams and character streams are incompatible for linking as the first one operates on 8-bit ASCII characters and the other on 16-bit Unicode characters. To link them explicitly, two classes exist in java.io package, InputStreamReader and OutputStreamWriter.
InputStreamReader links a byte stream, with the character stream BufferedReader (on reading-side) .
Whereas with the OutputStreamWriter, the characters of 2-bytes are encoded (converted) into bytes of 1-byte (InputStreamReader does it other way – bytes to characters).
For a Java program to interact with a server-side process it simply must be able to write to a URL, thus providing data to the server. It can do this by following these steps:
1.Create a URL.
2.Retrieve the URLConnection object.
3.Set output capability on the URLConnection.
4.Open a connection to the resource.
5.Get an output stream from the connection.
6.Write to the output stream.
7.Close the output stream.
Now in the snippet you provided ,
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
creates an output stream on the connection and opens an
OutputStreamWriter on it--Step 5 If the URL does support output, then
this method returns an output stream that is connected to the input
stream of the URL on the server side — the client's output is the
server's input.If the URL does not support output, getOutputStream
method throws an UnknownServiceException.
And
wr.write( data );
wr.close();
wr.flush();
It writes the required information to the output stream and closes the
stream. The data written to the output stream on the client side is
the input on the server side.
It's writing it to the output stream of the URLConnection - which is basically used for the body of an HTTP request (assuming it's an HTTP URL, of course).

URLConnection encoding issue with accent character

I've got an issue with the URLConnection encoding trying to send a text.
My code is this:
final URL url = new URL(urlString);
final URLConnection urlConnection = url.openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
urlConnection.setRequestProperty("Accept-Charset", "UTF-8");
final DataOutputStream urlDataOut = new DataOutputStream(urlConnection.getOutputStream());
urlDataOut.writeBytes(prepareData.toString());
urlDataOut.flush();
urlDataOut.close();
My prepareData.toString() contains a word with an "è" and as soon as the urlDataOut is written it will contain the diamond with the question mark instead of the "è" letter and the status of the write is FAILURE.
Does anybody know how to face this issue?
The method DataOutputStream.writeBytes method is not suitable for any character encoding. Its documentation says:
Each character in the string is written out, in sequence, by discarding its high eight bits.
Using the method writeUTF will not be feasible either. It writes two bytes containing the length of the encoded String (number of bytes) which the server would interpret as characters at the beginning.
So you should use the standard way of writing text to an OutputStream:
Writer w=new OutputStreamWriter(
urlConnection.getOutputStream(), StandardCharsets.UTF_8);
w.write(prepareData.toString());
w.flush();
w.close();

Categories

Resources