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

为什么Go实现的图片上传接口上传2.5MiB及以上文件会触发连接重置?

问题根因
  • 你当前的代码在判断请求体超过大小限制后,没有读取完整请求体就直接返回错误响应。当未读的请求体数据超过操作系统内核Socket缓冲区的默认阈值(通常为2~2.5MiB)时,内核会直接发送RST包强制断开TCP连接,不会走正常的连接关闭流程,这就是「连接被重置」报错的来源。
  • 浏览器检测到请求被异常重置后,会自动重试一次POST请求,所以你会看到handler连续打印两次File too large日志。2.4MiB的文件未读数据刚好低于缓冲区阈值,内核会等响应发送完成后正常断开连接,因此不会触发重置和重试。
解决方案

Go标准库提供了规范的请求体大小限制方案,使用http.MaxBytesReader包裹请求体即可,它会自动处理超限场景,同时消耗剩余的请求体避免连接异常断开:

// 需要额外导入io包
import (
    "io"
    "log"
    "net/http"
)

func postHandler(w http.ResponseWriter, r *http.Request) {
    // 限制最大请求体为1MiB,超限会自动向客户端返回413错误
    r.Body = http.MaxBytesReader(w, r.Body, 1<<20)
    // 读取请求体(如果是上传文件可以后续传给multipart解析,不需要提前全读)
    _, err := io.ReadAll(r.Body)
    if err != nil {
        log.Println("File too large")
        return
    }
    // 后续正常处理上传逻辑
}

如果你不想提前读取请求体,也可以在返回错误前手动消耗完剩余请求体:

func postHandler(w http.ResponseWriter, r *http.Request) {
    if r.ContentLength > 1<<20 {
        log.Println("File too large")
        // 消耗全部剩余请求体
        _, _ = io.Copy(io.Discard, r.Body)
        _ = r.Body.Close()
        // 注意你原代码里这里的错误描述写错了,是请求体过大不是响应过大
        http.Error(w, "request too large", http.StatusRequestEntityTooLarge)
        return
    }
    // 正常处理逻辑
}

内容的提问来源于stack exchange,提问作者urist

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 06:15:05