2

当我尝试从响应对象中获取 ServletOutputStream 对象时,我得到了 java.lang.IllegalStateException。下面是我的代码:

<%@ 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);
}
%>

以下是堆栈跟踪:

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)
4

4 回答 4

5

您正试图通过 JSP 文件中的某些代码下载文件。JSP 作为一种视图技术实际上是不适合这项工作的工具。外部的所有<% %>内容(通常是基于文本的内容,如 HTML、XML、JSON 等)也会写入 HTTP 响应,包括空格。这只会破坏由 Java 代码编写的下载内容的完整性,如果您正在提供诸如文档/音频/视频文件之类的二进制文件,则更是如此。

您的具体问题是由于 JSP 内部使用response.getWriter()打印所有模板内容(外部的所有内容<% %>)然后您尝试使用getOutputStream(). 这是一个非法的状态。您不能在一个响应中同时使用它们。除了使用getWriter(),您可以通过删除外部的任何空格来解决它<% %>,包括换行符。

所以,更换

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

<%
    // Your Java code.
%>

经过

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

(并确保在最后一个之后也没有尾随空格/换行符%>

但是,您实际上不应该使用 JSP 来完成这项工作。正如所说的工作的错误工具。您应该使用普通的HTTP servlet 类来完成这项工作。只需创建一个扩展类HttpServlet并将您在 JSP 中的所有 Java 代码移动到该doGet()方法中即可。最后将该 servlet 映射到 URL 并调用该 URL。

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

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

}

您可以在本文中找到更具体的示例。

也可以看看:

于 2013-01-01T12:56:41.813 回答
0

您收到错误是因为response.getWriter();之前已经调用过response.getOutputStream();。在服务呼叫中呼叫getWriter()和呼叫都是非法的。getOutputStream()和 JSP 的,默认使用getWriter().

尝试更换

ServletOutputStream outs = response.getOutputStream(); 

PrintWriter outs = response.getWriter();
于 2013-01-01T12:18:08.723 回答
0
  1. 您是否尝试过使用 jsp 上隐含的“out”?

  2. 您的程序是否有权从磁盘读取文件?

谢谢,
普拉泰克

于 2013-01-01T12:23:21.943 回答
0

我建议在 servlet 中编写文件下载代码。像这样的东西:

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");
        }
    }

你可以在你的jsp中有一个按钮说“下载”,在onclick的地方,应该调用上面的servlet。通过这种方式,您可以在 JSP 中打印日志。

于 2018-09-27T07:23:38.587 回答