上传大文件-错误VirtualAllocofx字节失败,errno=1455致命错误:内存不足

我有 10GB 的大文件,我试图通过 Postman 在 Go 中使用 multipart/form-data 上传。由于我不太了解 Go 中文件上传的工作原理,所以我在 YouTube 上找到了教程。

文件上传适用于较小的文件,但在较大的文件上总是崩溃并显示以下消息:“运行时:9193373696 字节的 VirtualAlloc 失败,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:UsersPcgosrcgithub.comtestuptest"
    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)

回答

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

来自文档:

ParseMultipartForm 将请求正文解析为 multipart/form-data。整个请求正文被解析,其文件部分的总共 maxMemory 字节存储在内存中,其余部分存储在磁盘上的临时文件中。ParseMultipartForm 必要时调用 ParseForm。对 ParseMultipartForm 调用一次后,后续调用无效。

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

对于处理大文件上传,我建议查看一下MultipartReader()

来自文档:

MultipartReader 返回 MIME 多部分阅读器,如果这是多部分/表单数据或多部分/混合 POST 请求,否则返回 nil 和错误。使用此函数代替 ParseMultipartForm 将请求正文作为流处理。

这是一种更快的方法并且不会消耗太多资源,这是因为我们将具有使用 将主体(这是一个流数据)直接存储到目标文件中的优势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:UsersPcgosrcgithub.comtestuptest"
    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


以上是上传大文件-错误VirtualAllocofx字节失败,errno=1455致命错误:内存不足的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>