3

I'm getting a java.lang.IllegalStateException when I try to get a ServletOutputStream object from the response object. Below is my code:

<%@ page import="java.util.*,java.io.*"%>             

<%
try {
    System.out.print("request came");
    File f = new File ("E:/dd.txt");

    String name = f.getName().substring(f.getName().lastIndexOf("/") + 1,f.getName().length());
    InputStream in = new FileInputStream(f);

    ServletOutputStream outs = response.getOutputStream();

    response.setContentType ("application/txt");
    response.setHeader ("Content-Disposition", "attachment; filename="+f.getName()+"");
    int bit = 256;
    int i = 0;
    try {
        while ((bit) >= 0) {
            bit = in.read();
            outs.write(bit);
        }
    } catch (IOException ioe) {
        ioe.printStackTrace(System.out);
    }
    outs.flush();
    outs.close();
    in.close();         
} catch (Exception ioe) {
    ioe.printStackTrace(System.out);
}
%>

The following is the stacktrace:

java.lang.IllegalStateException
   at org.apache.jasper.runtime.ServletResponseWrapperInclude.getOutputStream(ServletResponseWrapperInclude.java:63)
   at org.apache.jsp.html.portlet.vitage.custom.QUADWAVE.Procfiledownloadess1_005f36901_005f48.filedownload.downloadscreen_jsp._jspService(downloadscreen_jsp.java:5
   at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
   at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331)
   at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:329)
   at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
ameenulla
  • 33
  • 1
  • 1
  • 5
  • 1
    r u trying to download file using JSP? – Rajesh Jan 01 '13 at 11:28
  • It actually surprises me that you initially tagged the question with `[servlets]` (which is the correct answer to your question!) even though you are not using a servlet at all, but a JSP file. – BalusC Jan 01 '13 at 13:03
  • See http://stackoverflow.com/a/1776268/733092 for a quick answer that works. – Noumenon Dec 06 '16 at 03:40

4 Answers4

5

You're attempting to download a file by some code in a JSP file. JSP as being a view technology is actually the wrong tool for the job. Everything outside <% %> (which is normally text based content like HTML, XML, JSON, etc) is written to the HTTP response as well, including whitespace. This would only corrupt the integrity of the downloaded content which is written by Java code, even more so if you're serving binary files such as document/audio/video files.

Your concrete problem is caused because JSP internally uses response.getWriter() to print all the template content (everything outside <% %>) and then you're attempting to use getOutputStream(). This is an illegal state. You can't use them both simultaneously on a single response. Apart from using getWriter() instead, you could solve it by removing any whitespace outside <% %>, including newlines.

So, replace

<%@ page import="java.util.*,java.io.*"%>             

<%
    // Your Java code.
%>

by

<%@ page import="java.util.*,java.io.*"%><%
    // Your Java code.
%>

(and make absolutely sure that there's no trailing whitespace/newline after the last %> as well)

However, you should actually not be using JSP for the job. It's as said the wrong tool for the job. You should be using a normal HTTP servlet class for the job. Just create a class extending HttpServlet and move all the Java code which you've there in the JSP into the doGet() method. Finally map that servlet on an URL and invoke that URL instead.

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Your Java code.
    }

}

You can find a more concrete example in this article.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
1

I suggest writing the file download code in the servlet. Something like this:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

        ServletContext sc = request.getServletContext();
        String logFilename = (String) sc.getAttribute("scriptFilename");
        String logFilepath = DOWNLOAD_DIR + File.separator + logFilename + LOGFILE_EXTN;
               log.debug("file name received: "+logFilename);
               log.debug("log file path: "+logFilepath);

        File logFile = new File(logFilepath);
        OutputStream outStream = null;
        FileInputStream inputStream = null;

        if(logFile.exists() && logFile.length()!=0) {

            log.debug(logFile.getName()+": file exits in the directory.");
            String MIME_TYPE = "application/octet-stream";
            response.setContentType(MIME_TYPE);

            String headerKey = "Content-Disposition";
            String headerValue = String.format("attachment; filename=\"%s\"", logFile.getName());
            response.setHeader(headerKey, headerValue);

            try {

                outStream = response.getOutputStream();
                inputStream = new FileInputStream(logFile);
                byte[] buffer = new byte[BUFFER_SIZE];
                int bytesRead = -1;

                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outStream.write(buffer, 0, bytesRead);
                }

            }catch(IOException io) {

                log.debug("exception occured.."+io.getMessage());

            } finally {

                if(inputStream != null) {

                    inputStream.close();
                }

                outStream.flush();
                if(outStream != null) {

                    outStream.close();
                }
            }

        }else {

            log.debug(logFile.getName()+" :file not found in the directory.");
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "Jmeter Log file not found");
        }
    }

And you can have a button in your jsp say 'download' where onclick, the above servlet should be called. In this way you can have the logs getting printed in JSP.

colidyre
  • 4,170
  • 12
  • 37
  • 53
Syed
  • 11
  • 3
0

You are getting the error because response.getWriter(); was already called before response.getOutputStream();. It is illegal to call both getWriter() and getOutputStream() in a service call. And JSP's, by default use getWriter() .

Try replacing

ServletOutputStream outs = response.getOutputStream(); 

with

PrintWriter outs = response.getWriter();
Ramesh PVK
  • 15,200
  • 2
  • 46
  • 50
0
  1. did you tried using "out" which is implicitly present on jsp?

  2. Does your program has permissions to read files from disk?

Thanks,
Prateek

Prateek
  • 523
  • 2
  • 13