You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot服务中断Chunked编码POST大文件时客户端无法获取响应码的问题咨询

Spring Boot服务中断Chunked编码POST大文件时客户端无法获取响应码的问题咨询

我遇到了一个关于Spring Boot HTTP REST服务处理Chunked编码POST请求的棘手问题,想请教大家的解决方案:

场景说明

我有一个基于Java Spring Boot的HTTP REST服务,负责接收POST请求,需求是当上传的文件超过指定大小限制时,返回对应的错误码。但现在的问题是,客户端使用了Transfer-Encoding: chunked编码方式,导致在请求体传输完成前,服务端无法预知文件的总大小。

当前实现与遇到的问题

服务端当前的处理逻辑是:在接收数据的过程中持续统计字节数,一旦计数器超过设定的大小限制,就立即返回413 Request Entity Too Large错误并关闭连接。但此时客户端还在继续传输数据,这直接导致客户端抛出java.net.SocketException: Broken pipe异常,完整的堆栈信息如下:

java.net.SocketException: Broken pipe
at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:420)
at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1035)
at org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection$1.write(DefaultBHttpClientConnection.java:231)
at org.apache.hc.core5.http.impl.io.SessionOutputBufferImpl.flushBuffer(SessionOutputBufferImpl.java:117)
at org.apache.hc.core5.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:150)
at org.apache.hc.core5.http.impl.io.ChunkedOutputStream.flushCache(ChunkedOutputStream.java:127)
at org.apache.hc.core5.http.impl.io.ChunkedOutputStream.flush(ChunkedOutputStream.java:234)
at org.apache.hc.client5.http.entity.mime.InputStreamBody.writeTo(InputStreamBody.java:92)
at org.apache.hc.client5.http.entity.mime.AbstractMultipartFormat.doWriteTo(AbstractMultipartFormat.java:165)
at org.apache.hc.client5.http.entity.mime.AbstractMultipartFormat.writeTo(AbstractMultipartFormat.java:188)
at org.apache.hc.client5.http.entity.mime.MultipartFormEntity.writeTo(MultipartFormEntity.java:109)
at org.apache.hc.client5.http.impl.classic.RequestEntityProxy.writeTo(RequestEntityProxy.java:106)
at org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:252)
at org.apache.hc.core5.http.impl.io.HttpRequestExecutor.execute(HttpRequestExecutor.java:141)
at org.apache.hc.core5.http.impl.io.HttpRequestExecutor.execute(HttpRequestExecutor.java:218)
at org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager$InternalConnectionEndpoint.execute(PoolingHttpClientConnectionManager.java:712)
at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.execute(InternalExecRuntime.java:216)
at org.apache.hc.client5.http.impl.classic.MainClientExec.execute(MainClientExec.java:116)
at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
at org.apache.hc.client5.http.impl.classic.ConnectExec.execute(ConnectExec.java:188)
at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
at org.apache.hc.client5.http.impl.classic.ProtocolExec.execute(ProtocolExec.java:192)
at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
at org.apache.hc.client5.http.impl.classic.HttpRequestRetryExec.execute(HttpRequestRetryExec.java:96)
at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
at org.apache.hc.client5.http.impl.classic.ContentCompressionExec.execute(ContentCompressionExec.java:152)
at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
at org.apache.hc.client5.http.impl.classic.RedirectExec.execute(RedirectExec.java:115)
at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
at org.apache.hc.client5.http.impl.classic.InternalHttpClient.doExecute(InternalHttpClient.java:170)
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:245)
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:188)
at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:162)
...
Suppressed: java.net.SocketException: Broken pipe
at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:420)
at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1035)
at org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection$1.write(DefaultBHttpClientConnection.java:231)
at org.apache.hc.core5.http.impl.io.SessionOutputBufferImpl.flushBuffer(SessionOutputBufferImpl.java:117)
at org.apache.hc.core5.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:150)
at org.apache.hc.core5.http.impl.io.ChunkedOutputStream.flushCache(ChunkedOutputStream.java:127)
at org.apache.hc.core5.http.impl.io.ChunkedOutputStream.finish(ChunkedOutputStream.java:184)
at org.apache.hc.core5.http.impl.io.ChunkedOutputStream.close(ChunkedOutputStream.java:245)
at org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:253)
... 23 more

我先后尝试了java.net.http和org.apache.hc.client5.http两种客户端实现,但看起来一旦触发了IOException,客户端就完全无法获取到服务端已经返回的413响应码。

我的疑问

  • 有没有办法让客户端在抛出IOException的情况下,依然能够获取到服务端返回的413响应码?
  • 更通用的问题是:对于使用Transfer-Encoding: chunked的POST请求,提前中断请求的正确处理方式应该是什么?

备注:内容来源于stack exchange,提问作者Denis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 12:22:44