我的应用程序服务器。wav文件,可以从某些url下载。我必须改变逻辑,使它们将流式传输而不是被下载-所以我将删除被显式设置的Content-Disposition头。
代码:
// removed
//response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
bis = new BufferedInputStream(inputStream);
bos = new BufferedOutputStream(sOutputStream);
byte[] buff = new byte[10000];
int bytesRead = 0;
while(-1 != (bytesRead = bis.read(buff))) {
bos.write(buff, 0, bytesRead);
}
bos.flush();
第二次或第三次呼叫bos.write
原因
ClientAbortException: java.net.SocketException: socket write error: Connection aborted by peer
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:402)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:449)
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:349)
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:425)
at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:414)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:89)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
当我调试代码时,在write方法失败的时候,浏览器打开一个播放器,另一个相同的请求正在生成并成功。
设置了Content-Disposition,一切正常。什么好主意吗?
这是因为客户端在注意到它实际上是一个媒体文件后中止了请求,并通过客户端的媒体播放器通过HTTP Range
请求切换到流模式,以提高缓冲速度。然后,客户端将对文件的不同部分发起多个HTTP请求(显然,只有当您的servlet也真正支持它时,这才有效地工作……很多自定义的文件servlet没有,最终可能会表现得更差)。
对于服务器日志中的客户端中止异常,最好的办法是过滤并抑制它们,或者至少使用DEBUG/INFO在线日志而不是使用整个堆栈跟踪。
参见:
- 如何使用Servlet流式传输MP3, MP4, AVI等音频/视频文件
- ClientAbortException在应用程序部署在jboss与IE8浏览器