Java servlet未写入响应字节

Java servlet未写入响应字节,java,tomcat,servlets,Java,Tomcat,Servlets,我运行了一些Java servlet(3.x-Tomcat8),它们生成并返回PDF文档。我从来没有遇到过任何问题。我最近编写了一个新的servlet来创建和返回一个PDF文档,这个新servlet使用了与其他servlet完全相同的响应代码: response.reset(); response.setContentType("application/pdf"); response.setHeader("Content-Transfer-Encoding", "binary"); respon

我运行了一些Java servlet(3.x-Tomcat8),它们生成并返回PDF文档。我从来没有遇到过任何问题。我最近编写了一个新的servlet来创建和返回一个PDF文档,这个新servlet使用了与其他servlet完全相同的响应代码:

response.reset();
response.setContentType("application/pdf");
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\""+filename+".pdf\""); 
response.setContentLength(pdfBytes.length);

System.out.println("# Bytes => " + pdfBytes.length);

ServletOutputStream sos = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(sos);
bos.write(pdfBytes);
sos.flush();
sos.close();
正如我所说的,它与其他servlet一起工作得很好,但是当我调用新的servlet时,它返回0字节,即使上面的print语句有一个非零值

但是,如果我将上面的响应编写代码更改为:

OutputStream os = response.getOutputStream();
os.write(pdfBytes);
os.flush();
os.close();

…它工作正常,返回格式良好的PDF文档。为什么会发生这种情况?

您没有刷新
BufferedOutputStream
——因此它正在缓冲所有数据。您应该刷新它,而不是
ServletOutputStream

但是,如果您只编写一个单字节数组,那么无论如何使用
BufferedOutputStream
都没有意义,而且您也不需要显式刷新,因为关闭将刷新。所以你只需要:

ServletOutputStream sos = response.getOutputStream();
sos.write(pdfBytes);
// Unclear whether *this* is needed, either.
sos.close();

我个人希望servlet容器关闭输出流,但文档中不清楚。如果发生异常,是否要关闭它是另一回事…

您应该真正刷新并关闭
bos
而不是
sos

不应该
sos.flush()be
bos.flush()等等?这很有效!但我不明白。为什么其他servlet使用相同的代码工作正常?@RTF:我怀疑它们不是真的正常。或者它们只是因为写入的数据大于缓冲区大小才起作用。你那里的代码肯定是坏的。我可以从一些博客文章中复制和粘贴,并假设它是正确的。看起来我有点重构要做,因为我没有为响应代码创建样板函数!