There is client and server components, the client is sending the data in more secure way by converting the data in blob using POST method to the server.
Can any suggest me how to convert that blob data to string object in server side(Java).i have tried some code below
Way 1):
==============================
String streamLength = request.getHeader("Content-Length");
int streamIntLength = Integer.parseInt(streamLength);
byte[] bytes = new byte[streamIntLength];
request.getInputStream().read(bytes, 0, bytes.length);
String content = DatatypeConverter.printBase64Binary(bytes);
System.out.println(content);
Output for above code is : some junk data is displaying.
dABlAG0AcABsAGEAdABlAD0AMgAzADUAUgBfAFAAcgBvAHYAaQBkAGUAcgBfA
Way 2) :
======
BufferedReader reader = new BufferedReader(new InputStreamReader(
request.getInputStream()));
StringBuilder sb = new StringBuilder();
for (String line; (line = reader.readLine()) != null;) {
String str = new String(line.getBytes());
System.out.println(str);
}
Please suggest me any one, above both ways are not worked out.
Below code works for me.
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
String streamLength = request.getHeader("Content-Length");
int streamIntLength = Integer.parseInt(streamLength);
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(
inputStream));
char[] charBuffer = new char[streamIntLength];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
}
String body = stringBuilder.toString();
//System.out.println(body);
byte[] bytes = body.getBytes();
System.out.println(StringUtils.newStringUtf16Le(bytes));
From the first approach, it looks like the data is encoded (possibly in Base64 format). After decoding it, what is the problem you are facing ? If the data is String and then encoded to Base64, you should get the actual string after decoding it. (Assuming platform locales on client and server side are same).
If its a binary data, better you keep it inside a byte stream only. If you anyhow want it to convert to a string, then the first approach looks okay.
If this binary data represents some kind of file, you can get the related information using the HTTP headers and write it to temp location for further use.
Related
I have an API to which client can make request by sending the compressed request. Compression is done using the Deflator following way.
Request payload:
public byte[] compressRequest(String requestString) {
int reqLength = requestString.length();
int temp = (int)(1.001D * (double)reqLength + 1.0D) + 12;
byte[] byteArr = requestString.getBytes("US-ASCII");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(temp);
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream);
deflaterOutputStream.write(byteArr);
deflaterOutputStream.close();
return byteArrayOutputStream.toByteArray();
}
At the server side, I am trying to extract and decompress the data following way.
The same code is working fine on Java7 and Servlet based application. But in java 8 and Spring boot based application I am getting following exception java.io.EOFException: Unexpected end of ZLIB input stream at line inputLine = in.readLine())
#PostMapping(value = "saverecord")
public void hello(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("application/binary");
InflaterInputStream is = InflaterInputStream(request.getInputStream());
String requestXMLStr = extract(is, 0);
ServletOutputStream out = response
.getOutputStream();
// some processing and return response
}
private String extract(InputStream is) throws IOException {
StringBuffer sb = new StringBuffer();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
return sb.toString();
}
I tried following two things suggested in other SO answers, but neither worked.
InflaterInputStream is = InflaterInputStream(request.getInputStream(), new Inflater(false)); // tried true also
tried setting up encoding
BufferedReader in = new BufferedReader(new InputStreamReader(is, "US-ASCII"));
PS: For some project specific reasons I cannot use #RequestBody in the project.
I am using post man to send the JSon request. Then I get the inputStream using the getInputStream().
InputStream inputStream = request.getInputStream();
I have a JSon request with 2032 character and it might increase based on the scenarios. I tried few suggestions for the similar kind of issue, but using all I would be able to read only 1011 character.
Below are the ways which I tried.
Declarations:
BufferedReader bufferedReader = null;
StringBuilder stringBuilder = new StringBuilder();
// stringBuilder.ensureCapacity(1048576);
JSONObject jObj = null;
InputStream inputStream = request.getInputStream();
1)
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[1048576];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
2)
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
String result = "";
while ((line = bufferedReader.readLine()) != null)
result += line;
inputStream.close();
3)
String line;
try {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
} catch (Exception e) {
// TODO: handle exception
}
4)
stringBuilder.ensureCapacity(1048576);
BoundedInputStream boundedInputStream = new BoundedInputStream(inputStream);
bufferedReader = new BufferedReader(new InputStreamReader(boundedInputStream, "UTF-8"));
// StringBuilder builder= new StringBuilder();
StringBuilderWriter bufferedwriter = new StringBuilderWriter(stringBuilder);
IOUtils.copy(bufferedReader, bufferedwriter);
5)
bufferedReader = request.getReader();
char[] charBuffer = new char[1048576];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
Final Consumption: Used the second variation result was my latest try
// jObj = new JSONObject(stringBuilder.toString());
// jObj = new JSONObject(bufferedwriter.toString());
jObj = new JSONObject(result.toString());
Note: I was just verifying by increasing the char capacity to 1048576 to see if that would solve. But increasing that also have no effect on the inputstream.
Could anyone of you please advise me on how to read large Json input. Also let me know if I am doing it wrong.
Thanks in advance.
You seem to want to convert the JSON into a String. With Java 8 this has become a bit simpler.
// (1)
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
// (2)
String json = reader.lines().collect(Collectors.joining("\n"));
// do something with `json`...
}
Explained:
Create a BufferedReader from the input stream. Using "try-with-resources" means, that the reader will be automatically closed when leaving the try {} block.
The BufferedReader has a method lines() which returns a Stream<String>. You can simply join all Strings using the joining collector.
When I received an HTTP request of smaller length it's fine, but when receiving long packet getting corrupted. I took a trace through wire shark and I printed packet in hex value in JAVA console. Some additional values are showing in that printing. Why?
How can I solve it?
Is there anything wrong with conversion of HTTP request to Hex.
Following code is used to convert String to Hex.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream responseData = request.getInputStream();
byte[] buffer = new byte[1000];
int bytesRead = 0;
while ((bytesRead = responseData.read(buffer)) > 0) {
baos.write(buffer, 0, bytesRead);
sb=baos.toString();
str = baos.toString();
sb.append(str);
sb = new String(baos.toByteArray(),UTF8);
}
baos.close(); // connection.close();
You can't convert the read bytes to a String until all your input is read because a fraction of the input might be invalid UTF-8 encoded data.
Also don't use ByteArrayOutputStream.toString() because it uses the platform's default character set to decode bytes to characters (String) which is indeterministic. Instead use ByteArrayOutputStream.toString(String charsetName) and specify the encoding.
Also you should use ServletRequest.getCharacterEncoding() to detect encoding and revert to UTF-8 for example if it is unknown.
First read all input, and then convert it to a String:
String encoding = ServletRequest.getCharacterEncoding();
if (encoding == null)
encoding = "UTF-8";
// First read all input data
while ((bytesRead = responseData.read(buffer)) > 0) {
baos.write(buffer, 0, bytesRead);
}
// We have all input, now convert it to String:
String text = baos.toString(encoding);
Better Alternative
Since you convert the binary input to a String, you should use ServletRequest.getReader() instead of reading binary data using ServletRequest.getInputStream() and converting it to String manually.
E.g. reading all lines:
BufferedReader reader = request.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
// Process line, here I just append it to a StringBuilder
sb.append(line);
// If you want to preserve newline characters, keep the next line:
sb.append('\n');
}
My code reads from http connection and puts the data into an ByteArrayOutputStream.
The http data content has the first row with the update date/time and then the other data.
Example of data received from http url:
2012-03-02 03:06:34
text1
text2
text3
I have found this:
InputStream content = response.getEntity().getContent();
byte[] buffer = new byte[1024];
int numRead = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((numRead=content.read(buffer))!=-1){
baos.write(buffer, 0, numRead);
}
content.close();
String result = new String(baos.toByteArray());
How can I use the first row ("2012-03-02 03:06:34") and then the others row?
I'll think to use an array of strings and get the first row with baos[0] and the others with
for (int i=1;i<baos.length;i++) {...}
How I can?
Thanks.
my english is very ugly :-o
What you have works more on a byte-at-a-time level.
Try this for a line at a time:
InputStream is = response.getEntity().getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while((line = br.readLine()) != null)
{
//Do something with each line
}
In PHP we can use file_get_contents() like this:
<?php
$data = file_get_contents('php://input');
echo file_put_contents("image.jpg", $data);
?>
How can I implement this in Java (JSP)?
Here's a function I created in Java a while back that returns a String of the file contents. Hope it helps.
There might be some issues with \n and \r but it should get you started at least.
// Converts a file to a string
private String fileToString(String filename) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
StringBuilder builder = new StringBuilder();
String line;
// For every line in the file, append it to the string builder
while((line = reader.readLine()) != null)
{
builder.append(line);
}
reader.close();
return builder.toString();
}
This will read a file from an URL and write it to a local file. Just add try/catch and imports as needed.
byte buf[] = new byte[4096];
URL url = new URL("http://path.to.file");
BufferedInputStream bis = new BufferedInputStream(url.openStream());
FileOutputStream fos = new FileOutputStream(target_filename);
int bytesRead = 0;
while((bytesRead = bis.read(buf)) != -1) {
fos.write(buf, 0, bytesRead);
}
fos.flush();
fos.close();
bis.close();