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

低内存占用场景下Go服务大文件上传至Amazon S3的实现方案

大文件上传到S3的低内存占用优化方案

首先明确你关心的临时存储问题:Gin框架处理multipart/form-data请求时,默认会将小于32MB的请求体内容加载到内存,超过32MB的部分自动写入操作系统临时目录,不会全部占用内存,这个阈值可以通过engine.MaxMultipartMemory参数自定义调整。

下面是比「先写磁盘再分片上传」更优的两类方案:

方案1:无业务侧文件处理需求,优先使用S3预签名URL(最优解)

如果你的服务不需要对用户上传的文件做内容校验、转码、脱敏等中间处理,完全可以让用户直接上传到S3,不需要经过你的服务转发:

  • 你的服务只需要根据用户的上传请求,调用S3接口生成带有效期的上传预签名URL,返回给前端
  • 前端直接用这个URL把文件上传到S3,全程不占用你服务的带宽、内存、磁盘资源,也不存在两次上传的开销

方案2:必须经过服务转发的场景,用流式分片上传

如果确实需要服务做中间处理,也不需要先把整个文件存到本地磁盘,可以直接用AWS SDK自带的流式分片上传能力:
AWS Go SDK的manager.Uploader原生支持io.Reader输入,会自动把输入流切成分片并发上传到S3,你只需要把从请求里拿到的multipart.File直接传入即可,不需要预加载整个文件到内存,也不需要写入本地磁盘。
示例代码如下:

import (
    "context"
    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
    "github.com/aws/aws-sdk-go-v2/service/s3"
    "github.com/gin-gonic/gin"
)

func uploadHandler(c *gin.Context) {
    // 按需调整Gin的multipart阈值,比如调整为10MB,超过部分自动落临时盘
    // 可以在初始化Gin的时候全局设置:router.MaxMultipartMemory = 10 << 20
    
    fileHeader, err := c.FormFile("file")
    if err != nil {
        // 错误处理
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    
    file, err := fileHeader.Open()
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    defer file.Close()

    // 初始化S3上传器,按需配置分片大小、并发数
    uploader := manager.NewUploader(s3.NewFromConfig(awsConfig), func(u *manager.Uploader) {
        u.PartSize = 8 * 1024 * 1024 // 分片大小设为8MB,最小支持5MB
        u.Concurrency = 3 // 并发上传数
    })

    // 直接传入file这个io.Reader,流式上传,不需要加载整个文件
    _, err = uploader.Upload(context.TODO(), &s3.PutObjectInput{
        Bucket: aws.String("你的存储桶名"),
        Key:    aws.String(fileHeader.Filename),
        Body:   file,
    })
    if err != nil {
        c.JSON(500, gin.H{"error": "上传S3失败"})
        return
    }

    c.JSON(200, gin.H{"message": "上传成功"})
}

这种方案的内存占用只和你设置的分片大小、并发数有关,哪怕上传GB级的文件,内存占用也能稳定在几十MB级别,完全不会出现内存溢出的问题。

额外优化建议

如果需要支持超大文件(超过10GB)的断点续传,可以额外对接S3的分段上传API,前端把文件切成分片,每个分片单独上传到你的服务或者直接用预签名URL上传到S3,所有分片上传完成后再调用S3的合并接口完成整个文件的上传。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:09:04