为了账号安全,请及时绑定邮箱和手机立即绑定

上载大文件 - 错误 x 字节的虚拟分配失败,errno=1455 致命错误:内存不足

上载大文件 - 错误 x 字节的虚拟分配失败,errno=1455 致命错误:内存不足

Go
眼眸繁星 2022-09-19 17:14:54
我有10GB的大文件,我正在尝试通过Postman在Go中上传多部分/表单数据。由于我不太了解文件上传在Go中的工作原理,因此我在YouTube上找到了教程。文件上传适用于较小的文件,但在较大的文件上总是崩溃,并显示消息:“运行时:9193373696字节的虚拟Alloc失败,errno = 1455致命错误:内存不足”。以下是我尝试编写的代码:    err := r.ParseMultipartForm(500 << 20)    if err != nil {        fmt.Fprintln(w, err)    }    file, handler, err := r.FormFile("file")    if err != nil {        fmt.Fprintln(w, err)    }    fmt.Fprintln(w, handler.Filename)    fmt.Fprintln(w, handler.Size)    fmt.Fprintln(w, handler.Header.Get("Content-type"))    defer file.Close()    saveLocation := "C:\\Users\\Pc\\go\\src\\github.com\\test\\uptest"    tempFile, err := ioutil.TempFile(saveLocation, "upload")    if err != nil {        fmt.Fprintln(w, err)    }    defer tempFile.Close()    fileBytes, err := ioutil.ReadAll(file)    if err != nil {        fmt.Fprintln(w, err)    }    tempFile.Write(fileBytes)
查看完整描述

1 回答

?
FFIVE

TA贡献1797条经验 获得超6个赞

使用将要求您提供最大内存分配以临时存储上传的文件。如果您的文件大小很大(并且大于您分配的内存量),那么这对您的内存资源来说是个坏消息。ParseMultipartForm()

来自 文档:

解析多部分Form将请求正文解析为多部分/表单数据。对整个请求正文进行解析,其文件部分的内存字节最多最大存储在内存中,其余部分存储在磁盘上的临时文件中。如有必要,解析多部分窗体调用解析窗体。在对解析多部分窗体进行一次调用后,后续调用将不起作用。

根据您的错误消息,我们可以判断出问题的根本原因是由于上传的文件大于您分配的内存,即 。500 << 20

为了处理大文件上传,我建议看看。MultipartReader()

从 doc:

多部分读取器返回 MIME 多部分读取器,如果这是多部分/表单数据或多部分/混合 POST 请求,否则返回 nil 和错误。使用此函数而不是解析多部分窗体将请求正文作为流进行处理。

这是一种更快的方法,并且不会消耗太多资源,这是因为我们将具有使用直接将正文(即流数据)存储到目标文件的优点,而不是首先将其写入临时存储中。io.Copy()

的简单用法示例:MultipartReader()


reader, err := r.MultipartReader()

if err != nil {

    http.Error(w, err.Error(), http.StatusInternalServerError)

    return

}


for {

    part, err := reader.NextPart()

    if err == io.EOF {

        break

    }


    fmt.Println(part.FileName()) // prints file name

    fmt.Println(part.FormName()) // prints form key, in yor case it's "file"

    

    saveLocation := "C:\\Users\\Pc\\go\\src\\github.com\\test\\uptest"

    dst, err := os.Create(saveLocation)

    if dst != nil {

        defer dst.Close()

    }

    if err != nil {

        http.Error(w, err.Error(), http.StatusInternalServerError)

        return

    }


    if _, err := io.Copy(dst, part); err != nil {

        http.Error(w, err.Error(), http.StatusInternalServerError)

        return

    }

}

参考编号: https://pkg.go.dev/net/http#Request.ParseMultipartForm


查看完整回答
反对 回复 2022-09-19
  • 1 回答
  • 0 关注
  • 234 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号