What is the general approach to retrieve binary data that is posted to a Java Servlet? A byte[] is being posted to this servlet and I think I have to somehow parse the HttpServletRequest.getInputStream() and pull out the byte[] contents. Any ideas on how to change the below code to accomplish this?
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(
inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
String body = stringBuilder.toString();
System.out.println(body);
}
Don't wrap your inputstream in any "Reader"s, as they convert from bytes to characters, and you want the bytes.
yes. ditch all the Readers and use the InputStream you were handed on the 3rd line. if you don't understand the relationship between byte[] and InputStream, i would suggest reading the API docs and some good java tutorials.
Related
I have below code.
Content is coming in request which is non english and UTF-8 encoded. How to read it ? Currently i am doing this but looks like it is not correct.
private String readContent(HttpServletRequest request) throws IOException {
String body = null;
BufferedReader reader = null;
if (logger.isDebugEnabled()) {
logger.debug("Inside readContent() ...");
}
try {
// Read from request
StringBuilder buffer = new StringBuilder();
reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
// if (body != null) {
body = buffer.toString();
body.trim();
// }
} catch (IOException ex) {
throw ex;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
throw ex;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Leaving readContent() ..." + body);
}
return body;
}
I would do something like this and use Apache Commons IOUtils. You just need to specify your encoding.
InputStream inputStream = request.getInputStream();
String contentAsString = IOUtils.toString(inputStream, "UTF-8");
You can use a try /catch block to handle with the IOException that can be thrown. Or let your method throw an Exception that will be catched/handled somewhere else.
Is there any way to read inputStream of a request without losing the data in it.
I am trying to take a raw copy of my request into string before processing it. But once I read the inputstream from request, the inputstream is changing to null so, I can't get Parameter from my request later. I tried using CustomHttpServletRequestWrapper but it did not work. Below is the snippet of my code.
The InboundHandler is my handler class which has the processRequest(HttpServletRequest request, HttpServletResponse response) method that is invoked from my servlet class.
public class InboundHandler {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper(request);
String body = getRequestBody(requestWrapper.getInputStream());
String from = request.getParameter("from"); //which I'm getting null here
// I also tried using
// String from = requestWrapper.getParameter("from"); // Even this did not work
} catch (Exception e) {
e.printStackTrace();
}
}
private String getRequestBody(InputStream inputStream) {
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) != -1) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
}
} catch (IOException ex) {
ex.printStackTrace();
//throw new AuthenticationException("Error reading the request payload", ex);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException iox) {
// ignore
}
}
}
return stringBuilder.toString();
}
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
ex.printStackTrace();
//log.error("Error reading the request body...");
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
ex.printStackTrace();
//log("Error closing bufferedReader...");
}
}
}
body = stringBuilder.toString();
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream inputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return inputStream;
}
}
}
Q: Is there any way to read inputStream of a request without losing the data in it?
A: Yes - simply "save" what you "read"!
As Perdomoff correctly said, "Requests aren't meant to be reused". You can't put the water back in the hose once you've watered your garden :)
You can save the data. Perdomoff suggested using a session variable.
Another alternative might be to use a Servlet Filter. Here is a good tutorial:
http://www.journaldev.com/1933/java-servlet-filter-example-tutorial
I would like to filter a Post request in Filter (prior it getting to the Resource).
To filter the request I want to retrieve a token from the bode request and do some testing on it.
Current Resource:
#Post
public JsonRepresentation init(JsonRepresentation jRep) {
String token = jRep.getJsonObject().getString("token");
.
.
.
}
Current Filter:
#Override
protected int beforeHandle(Request request, Response response) {
int result = STOP;
String token = (String) Request.getCurrent().getAttributes().get("token");
.
.
.
}
These code does not retrieve the token.
My question is how can I retrieve a body request?
You can directly get the payload text of the request from its associated entity object, as described below:
Representation repr = request.getEntity();
String content = repr.getText();
Hope it helps you,
Thierry
you can try something like this to retreive the body :
public static String getBody(HttpServletRequest request) throws IOException {
String body = null;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
return body;
}
As it is dangerous to store request entities directly into memory (imagine if a client send a tera-bytes representation), the framework does not persist representations into memory by default, they can only be read once (from the socket).
I guess the answers to your issue may be read from here: Restlet reuse InputStream
I'm writing a Servlet in Java, that basically, gets a request with a XML in the Requests body, and then changes a few things in the XML and redirect/foreword the request with The new XML to a different Servlet that's on the same server, but its on a different web app.
I'm using doPost.
How do i do that? can i find code example any where?
Plus, whats the correct method to use:?
request.getRequestDispatcher().include /request.getRequestDispatcher().foreword / response.sendRedirect() or do i need to use the: HttpServletRequestWrapper?
this is what i have so far:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String body = getBody(request);
MapXml mapXml = new MapXml(body, "C:\\Projects\\XmlMapper\\output.xml","C:\\Projects\\XmlMapper\\output\\");
String outputXml = mapXml.getOutputXml();
}
public static String getBody(HttpServletRequest request) throws IOException {
String body = null;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
return body;
}
And i have no idea how to continue on from here. I'm new to the servlet world..
Thanks!!!
Cheers:)
I have a method can convert to a data to byte array and i must post it to a php web site. I am gonna use a java socket now. preparing that if i did i will add it here
it is data to byte[] methods , i found it in PDF to byte array and vice versa
public static byte[] readFully(InputStream stream) throws IOException
{
byte[] buffer = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bytesRead;
while ((bytesRead = stream.read(buffer)) != -1)
{
baos.write(buffer, 0, bytesRead);
}
return baos.toByteArray();
}
public static byte[] loadFile(String sourcePath) throws IOException
{
InputStream inputStream = null;
try
{
inputStream = new FileInputStream(sourcePath);
return readFully(inputStream);
}
finally
{
if (inputStream != null)
{
inputStream.close();
}
}
}
Here how to post a byte to php web site...
public static void postMybyte (String out)
{
try {
// Construct data
String data = URLEncoder.encode(out, "UTF-8") ;
// Send data
URL url = new URL("");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
System.out.println(" --->>>>"+line);
}
wr.close();
rd.close();
} catch (Exception e)
{
}
}