Reputation: 33
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)
Upvotes: 3
Views: 17417
Reputation: 11
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.
Upvotes: 1
Reputation: 1108537
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.
Upvotes: 6
Reputation: 15446
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();
Upvotes: -1
Reputation: 551
did you tried using "out" which is implicitly present on jsp?
Does your program has permissions to read files from disk?
Thanks,
Prateek
Upvotes: -1