0

0

如何使用Golang处理大文件上传_Golang io Reader大文件上传示例

P粉602998670

P粉602998670

发布时间:2026-01-03 15:28:02

|

364人浏览过

|

来源于php中文网

原创

直接读取大文件会导致内存爆炸,因http.Request.Body默认不流式处理;应避免io.ReadAll等全量加载函数,改用io.Copy到磁盘或按chunk读取。

如何使用golang处理大文件上传_golang io reader大文件上传示例

http.Request.Body 直接读取大文件会内存爆炸

Go 的 http.Request.Body 是一个 io.ReadCloser,但默认不会流式处理上传内容。如果直接用 io.ReadAll(r.Body)bytes.Buffer.ReadFrom(r.Body),整个文件会一次性加载进内存——上传 2GB 文件,进程 RSS 就涨 2GB,OOM 杀死是常态。

正确做法是边读边处理,不缓存全部内容。关键点在于:别调用任何会把整个 body 吃进去的函数。

  • 禁用:io.ReadAllio.Copy(ioutil.Discard, ...)(旧版)、json.NewDecoder(r.Body).Decode(...)(除非确认 body 很小)
  • 允许:io.Copy 到磁盘文件、multipart.Reader 解析表单、按 chunk 调用 Read()
  • 注意:r.ParseMultipartForm(32 会把文件头和小文件放进内存,MaxMemory 参数只是阈值,不是上限

multipart.Reader 安全解析含文件的表单

浏览器上传通常走 multipart/form-data,必须用 Go 标准库的 multipart 包解析,不能手动字符串切割或正则匹配 boundary。

核心逻辑是:先调用 r.MultipartReader() 获取 *multipart.Reader,再循环 NextPart(),对每个 part 检查 Header.Get("Content-Disposition") 是否含 filename=,再流式保存。

立即学习go语言免费学习笔记(深入)”;

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
mr, err := r.MultipartReader()
if err != nil {
    http.Error(w, "Invalid multipart request", http.StatusBadRequest)
    return
}

for {
    part, err := mr.NextPart()
    if err == io.EOF {
        break
    }
    if err != nil {
        http.Error(w, "Parse part failed", http.StatusBadRequest)
        return
    }

    filename := part.FileName()
    if filename != "" {
        out, err := os.Create("/tmp/upload/" + filename)
        if err != nil {
            http.Error(w, "Create file failed", http.StatusInternalServerError)
            return
        }
        _, err = io.Copy(out, part) // 流式写入,无内存压力
        out.Close()
        if err != nil {
            http.Error(w, "Save file failed", http.StatusInternalServerError)
            return
        }
    }
}
w.WriteHeader(http.StatusOK)

}

io.Copy 的底层行为和 buffer 大小影响

io.Copy 默认使用 io.DefaultCopyBuffer(目前是 32KB),它在内部分配一个临时 buffer,反复 ReadWrite,不会把整个源读进内存。这个大小足够平衡系统调用开销和内存占用,一般无需修改。

赣极购物商城网店建站软件系统
赣极购物商城网店建站软件系统

大小仅1兆左右 ,足够轻便的商城系统; 易部署,上传空间即可用,安全,稳定; 容易操作,登陆后台就可设置装饰网站; 并且使用异步技术处理网站数据,表现更具美感。 前台呈现页面,兼容主流浏览器,DIV+CSS页面设计; 如果您有一定的网页设计基础,还可以进行简易的样式修改,二次开发, 发布新样式,调整网站结构,只需修改css目录中的css.css文件即可。 商城网站完全独立,网站源码随时可供您下载

下载

但如果你要写入网络 socket 或低延迟设备,可能需要调小;写入机械硬盘且文件极大,可略增大(如 1MB)减少 write() 次数——不过实测提升有限,优先保证稳定性。

  • 自定义 buffer 示例:io.CopyBuffer(dst, src, make([]byte, 1
  • 不要用 bufio.Reader 包裹 r.Body 再传给 io.Copy:多余且可能破坏 multipart boundary 对齐
  • 上传中断时,io.Copy 返回的 n, errerr 可能是 net.ErrClosedio.ErrUnexpectedEOF,需区分处理

客户端上传超时与服务端 http.Server.ReadTimeout 配合

大文件上传慢,容易触发默认 30 秒的 ReadTimeout,导致连接被服务器强制关闭,客户端收到 408 Request Timeout 或直接断连。

必须显式延长读取超时,且建议比客户端最大预期上传时间多留 10–20 秒缓冲:

srv := &http.Server{
    Addr:         ":8080",
    Handler:      mux,
    ReadTimeout:  30 * time.Minute,
    WriteTimeout: 30 * time.Minute,
    IdleTimeout:  30 * time.Minute,
}
srv.ListenAndServe()

同时,Nginx / Caddy 等反代层也要同步调大 client_max_body_sizeclient_body_timeout,否则请求根本到不了 Go 进程。

真正难处理的是“上传中客户端断网”,此时 Go 不会立刻感知,得靠 TCP keepalive 或应用层心跳——但大多数文件上传场景下,依赖 ReadTimeout 已覆盖绝大多数异常。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

177

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

225

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

336

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

388

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

194

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

189

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

191

2025.06.17

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

194

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.1万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号