Java Servlet混合了标题和内容,并在输出中写入两次相同的内容?

Java Servlet混合了标题和内容,并在输出中写入两次相同的内容?,java,servlets,synchronization,Java,Servlets,Synchronization,我已经实现了一个行为不稳定的servlet,有时它在内容中混合了标题,并编写了两次相同的内容 有时它返回的文件包含由以下内容混合的响应头: Server: Apache-Coyote/1.1 : W/"43-1353687036000" DatCCoonntenntt--DDiissppoosittiioonn: : atatatacehnmte;n tf;i lfenlaemnea=m20=12201112211127325421_4W1_Wirnkgi_nSgc_Seern.xnlsx sx

我已经实现了一个行为不稳定的servlet,有时它在内容中混合了标题,并编写了两次相同的内容

有时它返回的文件包含由以下内容混合的响应头:

Server: Apache-Coyote/1.1
: W/"43-1353687036000"
DatCCoonntenntt--DDiissppoosittiioonn: : atatatacehnmte;n tf;i lfenlaemnea=m20=12201112211127325421_4W1_Wirnkgi_nSgc_Seern.xnlsx
sx
Content-Typ-eT: ype: applaipcatciaoti/on/toctestt-rstare
am
ConCtoententy-pTeype: appalicatcion/oon/octet-setarm
m
CCoonntent-Lnegtht h: 4199

Date: te: FriF,r i2,3  2No vNo2v0 120162: 215:25 :G4M2T 
....
File content bytes ...

And again same header and content
更新 *这种情况发生在Tomcat7上*

我也在Tomcat6和Jetty上进行了测试,在这两种情况下,没有向响应内容注入HTTP头,但HTTP头是错误的,返回了错误的文件名,文件内容是正确的文件。我注意到当 返回分块的传输编码。

当我删除头文件和字节的第二部分时,它是有效的文件。 是否可能是同步问题

更新 以下是servlet的完整源代码:

public class ExcelDownloadServlet extends HttpServlet
{
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger
            .getLogger (ExcelDownloadServlet.class);


    @Override
    protected void doGet (HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException
    {
        try
        {
            TransactionId transactionId = getTransactionId (request);
            String fileName =
                    request.getParameter (GlobalConstants.EXCEL_FILE);
            ExcelDownloadType downloadType =
                    ExcelDownloadType
                            .valueOf (request
                                    .getParameter (GlobalConstants.EXCEL_DOWNLOAD_TYPE));
            ActionContextFactory actionContextFactory =
                    ApplicationContext.getContext ()
                            .getActionContextFactory ();
            //suppress warning. HttpServletRequest.getLocales does not support generics
            @SuppressWarnings("unchecked")
            ActionContext actionContext =
                    actionContextFactory.create (request.getSession ()
                            .getId (), Collections.<Locale> list (request
                            .getLocales ()));
            GetExcelDataResponse dataResponse =
                    new GetExcelData (transactionId, fileName, downloadType)
                            .execute (actionContext);
            writeToResponse (response, dataResponse.getFileName (),
                    dataResponse.getData ());
        }
        catch (InvalidSessionException e)
        {
            LOG.error ("Invalid session in Excel download", e);
            throw new ServletException (e);
        }
        catch (ActionException e)
        {
            LOG.error ("Could not download into excel.", e);
            throw new ServletException (e);
        }
    }

    protected TransactionId getTransactionId (HttpServletRequest request)
    {
        return RequestParameterDeserializer.<TransactionId> deserialize (
                request, GlobalConstants.TRANSACTION_ID);
    }

    protected void writeToResponse (HttpServletResponse response,
            String rawFileName, byte[] data) throws IOException
    {
        ServletOutputStream sout = null;
        try
        {            
            response.setContentType ("application/octet-stream");
            response.setContentLength (data.length);
            // removing blanks from the file name, since FF cuts file names
            // otherwise.
            String fileNameWithTime = rawFileName.replaceAll (" ", "_");
            response.setHeader ("Content-Disposition", "attachment; filename="
                    + fileNameWithTime);
            sout = response.getOutputStream ();
            sout.write (data, 0, data.length);
        }
        finally
        {
            if (sout != null)
            {
                sout.close ();
            }
        }
    }
公共类ExcelDownloadServlet扩展了HttpServlet
{
私有静态最终长serialVersionUID=1L;
专用静态最终记录器日志=记录器
.getLogger(ExcelDownloadServlet.class);
@凌驾
受保护的无效数据集(HttpServletRequest请求,
HttpServletResponse响应)引发ServletException,IOException
{
尝试
{
TransactionId TransactionId=getTransactionId(请求);
字符串文件名=
request.getParameter(GlobalConstants.EXCEL_文件);
ExcelDownloadType下载类型=
ExcelDownloadType
.价值(请求)
.getParameter(GlobalConstants.EXCEL_下载_类型));
ActionContextFactory ActionContextFactory=
ApplicationContext.getContext()
.getActionContextFactory();
//禁止显示警告。HttpServletRequest.getLocales不支持泛型
@抑制警告(“未选中”)
ActionContext ActionContext=
actionContextFactory.create(request.getSession()
.getId(),Collections.list(请求
.getLocales());
GetExcelDataResponse数据响应=
新的GetExcelData(transactionId、文件名、下载类型)
.执行(actionContext);
writeToResponse(响应,dataResponse.getFileName(),
dataResponse.getData());
}
捕获(InvalidSessione异常)
{
LOG.error(“Excel下载中的会话无效”,e);
抛出新的ServletException(e);
}
捕获(动作异常e)
{
LOG.error(“无法下载到excel。”,e);
抛出新的ServletException(e);
}
}
受保护的TransactionId getTransactionId(HttpServletRequest请求)
{
return RequestParameterDeserializer.deserialize(
请求,GlobalConstants.TRANSACTION_ID);
}
受保护的无效writeToResponse(HttpServletResponse,
字符串rawFileName,字节[]数据)引发IOException
{
ServletOutputStream sout=null;
尝试
{            
response.setContentType(“应用程序/八位字节流”);
response.setContentLength(data.length);
//删除文件名中的空格,因为FF会剪切文件名
//否则。
字符串fileNameWithTime=rawFileName.replaceAll(“,”);
response.setHeader(“内容处置”、“附件;文件名=”
+文件名随时间变化);
sout=response.getOutputStream();
sout.write(数据,0,数据长度);
}
最后
{
如果(sout!=null)
{
sout.close();
}
}
}
更新
*当GWT应用程序在IFrame中生成带有所需参数和设置的servlet URL时,调用来自GWT应用程序,然后servlet调用和文件正在下载。有什么建议吗?*

我很久以前就遇到过类似的问题。 结果是,关闭ServletOutputStream触发了请求流上的意外行为

servlet不应该关闭容器提供的OutputStream。 另一个问题可能是手动设置内容长度,这是容器生成正确值的责任


总之,请尝试删除
out.close()
response.setContentLength()

如果您怀疑存在同步问题,我建议您发布整个servlet,因为一些同步问题是由servlet中定义的字段引起的。@kmb385我的意思是我应该同步我发布的部分代码吗?这是一个非常简单的servlet,它在输出中写入生成文件的给定字节数组,并且我混淆了它包含响应头等。由于为每个servlet创建了响应和请求的新实例,我认为不需要同步这段代码。您可以发布请求servlet的html或js吗。您有任何筛选器吗?确实,筛选器注入了一些
HttpServletResponseWrapper
错误地执行其工作的r。我指定了response.setContentLength(),我将尝试删除out.close(),此问题不经常发生,并且很难重现,谢谢您的回答