HTTP API 在写入文件时停止响应

问题描述

我使用 Gorilla Mux 在 Go 中编写了一个 API http 服务器。它运作良好。其中一个端点用于上传文件并将它们保存到挂载到服务器 pod 的 NFS 共享。客户端是一个使用 Alamofire 的 Swift 5 应用。

对于较小的文件,我们只使用 copy 从请求正文中写入它们。对于较大的文件,我们使用缓冲流读取器和写入器来执行写入,因为我们在仅使用复制时遇到超时和丢失问题。

然而,当写入发生时,服务器停止响应所有新请求。如何更改或优化此代码,以便服务器继续按预期响应?在此处查看代码

func uploadFile(w http.ResponseWriter,r *http.Request) {
    vars := mux.Vars(r)

    repoBase := "./repo/gkp-directory/"
    folderName := vars["uploadFolder"]
    fileName := vars["uploadFile"]
    fileSize := r.ContentLength

    //
    // Check if we have a package. They can be large and require special handling
    //
    if folderName == "pkgs" {
        defer r.Body.Close()

        //
        // If the content is more than 10MB write to temp cache then move it
        // in a seperate goroutine to the repo storage
        //
        if r.ContentLength > 10000000 {
            buf := make([]byte,10000000)

            tempFile,err := os.Create(repoBase + folderName + "/" + fileName)
            if err != nil {
                log.Println("ERROR: Failed to create file.")
                log.Println(err.Error())
                return
            }
            defer tempFile.Close()

            for {
                n,err := r.Body.Read(buf)
                if err != nil && err != io.EOF {
                    log.Println("ERROR: Error creating file on NFS")
                    log.Println(err.Error())
                    return
                }

                if n == 0 {
                    break
                }

                if _,err := tempFile.Write(buf[:n]); err != nil {
                    log.Println("ERROR: Error streaming to NFS")
                    log.Println(err.Error())
                    return
                }
            }
            tempFile.Close()
            r.Body.Close()

        } else {
            //
            // If the package is smaller than 10MB we should be safe to write it directly to
            // the NFS backend with no buffer
            //
            outputFile,err := os.Create(repoBase + folderName + "/" + fileName)
            if err != nil {
                log.Println("ERROR: Failed to create file.")
                log.Println(err.Error())
                return
            }

            defer outputFile.Close()
            written,err := io.copy(outputFile,r.Body)
            if err != nil {
                log.Println("ERROR: Failed to create file.")
                log.Println(err.Error())
                return
            }

            if written == fileSize {
                outputFile.Close()
                r.Body.Close()
            }
        }
    } else {
        //
        // Otherwise file is not a package. This means it is just a small text file we
        // should safetly be able to write this to NFS with no issues or buffer
        //
        outputFile,err := os.Create(repoBase + folderName + fileName)
        if err != nil {
            log.Println("ERROR: Failed to create file.")
            log.Println(err.Error())
            return
        }

        defer outputFile.Close()
        written,r.Body)
        if err != nil {
            log.Println("ERROR: Failed to create file.")
            log.Println(err.Error())
            return
        }

        if written == fileSize {
            outputFile.Close()
            r.Body.Close()
        }
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)