将 'Content-Encoding' 设置为 gzip 或 deflate 会导致 java.net.SocketException:连接重置
setting 'Content-Encoding' to gzip or deflate causes java.net.SocketException: Connection reset
我开发了一个简单的 Java Servlet,以便从服务器检索医疗文件 (DICOM):
public class DicomRetrieveServlet extends HttpServlet {
private static Logger log = Logger.getLogger(DicomRetrieveServlet.class);
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String dicomFilepath = "PATH TO MY FILE";
InputStream resultInStream = null;
response.setHeader("Accept-Ranges","bytes");
response.setHeader("Vary", "Accept-Encoding");
response.setHeader("Content-Encoding", "gzip");
response.setHeader("Access-Control-Allow-Origin","*");
response.setContentType("application/dicom");
try (OutputStream out = response.getOutputStream()) {
int bytes_read;
resultInStream = new FileInputStream(dicomFilepath.toString());
byte[] buffer = new byte[4096];
while ((bytes_read = resultInStream.read(buffer)) != -1) {
out.write(buffer, 0, bytes_read);
}
out.flush();
} catch (Exception e) {
log.error("Error while streaming DICOM image ", e);
}
}
如果我评论这一行:
response.setHeader("Content-Encoding", "gzip");
servlet 工作正常,但添加以上行会导致:
org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:367)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:331)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:101)
at pages.DicomRetrieveServlet.doGet(DicomRetrieveServlet.java:107)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.filters.CorsFilter.handleNonCORS(CorsFilter.java:438)
at org.apache.catalina.filters.CorsFilter.doFilter(CorsFilter.java:179)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:215)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
at org.apache.coyote.http11.InternalOutputBuffer.flush(InternalOutputBuffer.java:119)
at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:801)
at org.apache.coyote.Response.action(Response.java:172)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:363)
... 29 more
出于某些原因,我想模拟具有以下 HTTP 响应的其他服务器行为 Header:
HTTP/1.1 200 OK
Date: Fri, 29 Apr 2016 14:13:51 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Mon, 07 Apr 2014 18:40:46 GMT
ETag: "14034f-8257c-4f67834a723b4"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Access-Control-Allow-Origin: *
Content-Type: application/dicom
这些是 Http 请求 Headers:
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36
X-DevTools-Emulate-Network-Conditions-Client-Id: 922810C0-22E8-4F8A-8E15-894B36DAB06A
Accept: '*/*'
Referer: http://localhost:8080/myapp/viewImageCornerStone.jsf?studyUID=1.2.410.200028.456.20151027.10647
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,fa;q=0.6
Cookie: JSESSIONID=FABFF5F057EE4786E2920E5DFA47376C
我正在使用 'jdk1.8.0_77' 和 'apache-tomcat-7.0.62'。
任何帮助将不胜感激。
谢谢亲爱的@EJP 有用的评论,gzip 过滤器没有影响我的 Servlet,所以内容不是真正的 GZIP 格式,添加错误的内容编码导致了上述异常。
我删除了这条错误的语句:
response.setHeader("Content-Encoding","gzip");
并且我已将我的 servlet url 添加到 GZIP 过滤器 url 模式。
现在响应头状态良好:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Encoding: gzip
Accept-Ranges: bytes
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Content-Disposition: attachment; filename=1.2.410.200028.456.20151027.10647.1.1.dcm
Content-Type: application/dicom
Transfer-Encoding: chunked
日期:2016 年 5 月 2 日,星期一 12:54:45 GM
我开发了一个简单的 Java Servlet,以便从服务器检索医疗文件 (DICOM):
public class DicomRetrieveServlet extends HttpServlet {
private static Logger log = Logger.getLogger(DicomRetrieveServlet.class);
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String dicomFilepath = "PATH TO MY FILE";
InputStream resultInStream = null;
response.setHeader("Accept-Ranges","bytes");
response.setHeader("Vary", "Accept-Encoding");
response.setHeader("Content-Encoding", "gzip");
response.setHeader("Access-Control-Allow-Origin","*");
response.setContentType("application/dicom");
try (OutputStream out = response.getOutputStream()) {
int bytes_read;
resultInStream = new FileInputStream(dicomFilepath.toString());
byte[] buffer = new byte[4096];
while ((bytes_read = resultInStream.read(buffer)) != -1) {
out.write(buffer, 0, bytes_read);
}
out.flush();
} catch (Exception e) {
log.error("Error while streaming DICOM image ", e);
}
}
如果我评论这一行:
response.setHeader("Content-Encoding", "gzip");
servlet 工作正常,但添加以上行会导致:
org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:367)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:331)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:101)
at pages.DicomRetrieveServlet.doGet(DicomRetrieveServlet.java:107)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.filters.CorsFilter.handleNonCORS(CorsFilter.java:438)
at org.apache.catalina.filters.CorsFilter.doFilter(CorsFilter.java:179)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:215)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
at org.apache.coyote.http11.InternalOutputBuffer.flush(InternalOutputBuffer.java:119)
at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:801)
at org.apache.coyote.Response.action(Response.java:172)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:363)
... 29 more
出于某些原因,我想模拟具有以下 HTTP 响应的其他服务器行为 Header:
HTTP/1.1 200 OK
Date: Fri, 29 Apr 2016 14:13:51 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Mon, 07 Apr 2014 18:40:46 GMT
ETag: "14034f-8257c-4f67834a723b4"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Access-Control-Allow-Origin: *
Content-Type: application/dicom
这些是 Http 请求 Headers:
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36
X-DevTools-Emulate-Network-Conditions-Client-Id: 922810C0-22E8-4F8A-8E15-894B36DAB06A
Accept: '*/*'
Referer: http://localhost:8080/myapp/viewImageCornerStone.jsf?studyUID=1.2.410.200028.456.20151027.10647
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,fa;q=0.6
Cookie: JSESSIONID=FABFF5F057EE4786E2920E5DFA47376C
我正在使用 'jdk1.8.0_77' 和 'apache-tomcat-7.0.62'。
任何帮助将不胜感激。
谢谢亲爱的@EJP 有用的评论,gzip 过滤器没有影响我的 Servlet,所以内容不是真正的 GZIP 格式,添加错误的内容编码导致了上述异常。
我删除了这条错误的语句:
response.setHeader("Content-Encoding","gzip");
并且我已将我的 servlet url 添加到 GZIP 过滤器 url 模式。 现在响应头状态良好:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Encoding: gzip
Accept-Ranges: bytes
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Content-Disposition: attachment; filename=1.2.410.200028.456.20151027.10647.1.1.dcm
Content-Type: application/dicom
Transfer-Encoding: chunked
日期:2016 年 5 月 2 日,星期一 12:54:45 GM