如何在JSP文件中编写文件下载到响应

时间:2013-01-01 11:11:49

标签: jsp download

当我尝试从响应对象获取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);
}
%>

以下是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)

4 个答案:

答案 0 :(得分: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 class来完成工作。只需创建一个扩展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.
    }

}

您可以在this article中找到更具体的示例。

另见:

答案 1 :(得分:0)

您收到错误是因为response.getWriter();之前已调用response.getOutputStream();。在服务呼叫中同时呼叫getWriter()getOutputStream()是违法的。而JSP默认使用getWriter()

尝试替换

ServletOutputStream outs = response.getOutputStream(); 

PrintWriter outs = response.getWriter();

答案 2 :(得分:0)

  1. 您是否尝试使用隐含在jsp上的“out”?

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

  3. 谢谢,
    Prateek

答案 3 :(得分: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中打印日志。