Expand my Community achievements bar.

Learn about Edge Delivery Services in upcoming GEM session
SOLVED

java.lang.IllegalStateException: Request Data has already been read reading byte array in servlet

Avatar

Level 4

I have a code in java that sends byte[] to CQ servlet using POST. The code for sending is  :

            URL url = new URL("http://localhost:4503/bin/services/updateslafile"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); String authStr = "admin:admin"; // encode data on your side using BASE64 byte[] bytesEncoded = Base64.encodeBase64(authStr.getBytes()); String authEncoded = new String(bytesEncoded); connection.setRequestProperty("Authorization", "Basic "+authEncoded); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.setRequestProperty("fileName", "test.docx");         byte[] input;//assume input initialized with some .docx file content as byte[] OutputStream outs = connection.getOutputStream(); outs.write(input); outs.flush(); outs.close(); //for response reading StringBuffer strBuffer = new StringBuffer(); InputStream inputStream = connection.getInputStream(); byte[] b = new byte[1024]; while ( is.read(b) != -1) strBuffer.append(new String(b)); System.out.println("strbuffer : "+strBuffer.toString());

The code in the servlet for reading the byte[] is like below :

String fileName = request.getHeader("fileName"); // opens input stream of the request for reading data InputStream inputStream = request.getInputStream();// This line giving error String filePath = "/home/usr/documents/"+fileName; // opens an output stream for writing file FileOutputStream fileOuputStream = new FileOutputStream(filePath); byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = -1; LOGGER.info("Receiving data..."); while ((bytesRead = inputStream.read(buffer)) != -1) {           fileOuputStream.write(buffer, 0, bytesRead); } LOGGER.info("Data received."); fileOuputStream.close(); inputStream.close();

Now when I run the code in the error log I am getting some error 

08.03.2016 15:19:37.162 *ERROR* [127.0.0.1 [1457430567960] POST /bin/services/updateslafile HTTP/1.1] org.apache.sling.engine.impl.SlingRequestProcessorImpl service: Uncaught Throwable
java.lang.IllegalStateException: Request Data has already been read

Apart from this error I am also getting below error but I think this isn't relevant.

08.03.2016 15:17:31.092 *ERROR* [qtp87442412-7274] org.apache.sling.engine.impl.parameters.ParameterSupport getRequestParameterMapInternal: Error parsing request
java.lang.IllegalArgumentException: Bad escape sequence: %ۑ

I know request.getInputStream() is giving some issue but not sure how to fix it.

1 Accepted Solution

Avatar

Correct answer by
Level 4

Hi,

Actually I was getting object there. I converted that object back to raw byte array in the servlet and I got it workign. Code I used is as below :

    String encodingScheme = "UTF-8";     request.setCharacterEncoding(encodingScheme);     String requestStr = request.getParameter("inputstream");     byte[] rawRequestMsg = requestStr.getBytes(encodingScheme);

Now I am writing this byte[] to a file :

public boolean writeToSLAFile(String fileLocation,byte[] byteArray){ try{ String uploadedFileLocation = fileLocation; FileOutputStream fileOuputStream = new FileOutputStream(uploadedFileLocation); fileOuputStream.write(byteArray); fileOuputStream.close(); return true; }catch(IOException e){ LOGGER.error("IO Exception in WriteToSLAFile method"+e.getMessage(),e); } return false; }

Now the writing is successful, file is getting created but the file is corrupt. That I can fix. Thanks Scott.

Regards,

Samir

View solution in original post

5 Replies

Avatar

Level 10

You have to read an input stream in a sling servlet in a certain way. See this community article that shows you how to successfully read an input stream in a sling servlet: 

https://helpx.adobe.com/experience-manager/using/uploading-files-aem1.html

This will help you. 

PS - the article been updated for AEM 6.1. A new package too - which was tested by our AEM super community members. 

Avatar

Level 4

Hi Scott,

That piece of code I tried but its not working for me. I am posting the data using below code :

connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.setRequestProperty("fileName", filename); OutputStream outs = connection.getOutputStream(); outs.write(input); // input is byte[] outs.flush(); outs.close();

So in the code which you shared in the link first of all isMultipart is false, and if by any way I change it to true then the params comes as empty{}. So I think that code is only for file upload from form. Please suggest.

 

Regards,

Samir

Avatar

Level 4

Hi,

I did a little change in code and now I am getting something which I am not sure is correct or not. I am now setting it as parameter in the post request like below 

connection.setDoOutput(true);         connection.setRequestMethod("POST"); connection.setRequestProperty("fileName", filename); OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); System.out.println("input :"+input);// This prints input :[B@2d813d7b writer.write("inputstream="+input);  

Now the input being printed instead of complete byte[] sequence is just [B@2d813d7b and because I am sending the same in parameter, in my cq servlet I am using below code which is giving me only [B@2d813d7b :

                String requestStr = request.getParameter("inputstream");                 byte[] rawRequestMsg = requestStr.getBytes(someSingleByteEncoding);                 LOGGER.info(""+rawRequestMsg); // prints [B@2d813d7b

Now whats happening I don't know but this is definitely not my byte[] which I got by converting a .docx to byte[].

Any suggestions how to deal with this.

Thanks,

Samir

Avatar

Correct answer by
Level 4

Hi,

Actually I was getting object there. I converted that object back to raw byte array in the servlet and I got it workign. Code I used is as below :

    String encodingScheme = "UTF-8";     request.setCharacterEncoding(encodingScheme);     String requestStr = request.getParameter("inputstream");     byte[] rawRequestMsg = requestStr.getBytes(encodingScheme);

Now I am writing this byte[] to a file :

public boolean writeToSLAFile(String fileLocation,byte[] byteArray){ try{ String uploadedFileLocation = fileLocation; FileOutputStream fileOuputStream = new FileOutputStream(uploadedFileLocation); fileOuputStream.write(byteArray); fileOuputStream.close(); return true; }catch(IOException e){ LOGGER.error("IO Exception in WriteToSLAFile method"+e.getMessage(),e); } return false; }

Now the writing is successful, file is getting created but the file is corrupt. That I can fix. Thanks Scott.

Regards,

Samir

Avatar

Employee

This is the correct resolution.