java.lang.IllegalStateException从Web服务器下载文件时的servlet异常

时间:2015-06-25 23:21:18

标签: java servlets download struts2 stream

我有一些来自网络服务器的下载文件代码。 一切正常,但在控制台我有这个例外:

        июн 26, 2015 2:08:42 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [default] in context with path [/TestTask] threw exception
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
    at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:462)
    at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleErrorInDevMode(DefaultDispatcherErrorHandler.java:109)
    at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleError(DefaultDispatcherErrorHandler.java:57)
    at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:909)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:576)
    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

为什么以及它可以是什么?我怎么解决这个问题?我尝试在谷歌找到答案,但我失败了。

package actions;

import java.io.IOException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Action;

import org.apache.log4j.Logger;
import org.apache.struts.chain.contexts.ServletActionContext;

import service.CsvCreator;

import com.opensymphony.xwork2.ActionSupport;

public class DownloadCsvAction extends ActionSupport {

    private static final long serialVersionUID = -4714537109287679996L;
    private CsvCreator CSVcreator;
    private static final Logger logger = Logger.getLogger(DownloadCsvAction.class);

    public CsvCreator getCSVcreator() {
        return CSVcreator;
    }

    public void setCSVcreator(CsvCreator cSVcreator) {
        CSVcreator = cSVcreator;
    }

    @Override
    public String execute() {

        HttpServletResponse response = org.apache.struts2.ServletActionContext.getResponse();
        response.setHeader("Content-Disposition", "attachment; filename=\"phone_records.csv\"");
        response.setContentType("text/csv");

        ServletOutputStream out;
        try {
            out = response.getOutputStream();

            String tableHeader = "Caller, Event, Reciever, Timestamp\n";

            out.write(tableHeader.getBytes("UTF-8"));
            out.write(CSVcreator.getAllRecordsInString().getBytes("UTF-8"));

            out.flush();
            out.close();
        } catch (IOException e) {
            logger.error(e.getMessage());
        }

        return SUCCESS;
    }

}

我的struts.xml

<action name="DownloadCsvAction" class="DownloadCsvAction">
        <result name="success" type="dispatcher"/>
</action>

1 个答案:

答案 0 :(得分:2)

Why and what it can be?

Because response is already committed. You have closed response before it's used by the Struts2.

And how I can fix this problem?

When your action execution ends, return Action.NONE result code. This code tells the invoker to not execute any result because response might be already committed.

You can also rewrite the action implementation to use stream result type. In this way you have not to do with the response and let Struts2 do the rest. Example of using stream result is here.