如何处理同时具有多个输入和多个文件的请求

构建一个后端 go 服务器,该服务器可以采用具有多个输入的形式,其中 3 个具有多个文件输入。我搜索了一下,它指出,如果你想做这样的东西,你不想使用典型的


if err := r.ParseMultipartForm(32 << 20); err != nil {

        fmt.Println(err)

    }

    // get a reference to the fileHeaders

    files := r.MultipartForm.File["coverArt"]

相反,您应该使用


mr, err := r.MultipartReader()

    if err != nil {

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

    }

标准表单数据:

  1. 名字

  2. 电子邮件

  3. 封面图片照片(多个文件)

  4. 个人资料照片(多个文件)

  5. 2 音频文件 (2 歌曲)

  6. 2个视频(个人介绍,无伴奏合唱中的人物录音)

表单

<form method="post" enctype="multipart/form-data" action="/upload">

        <input type="text" name="name">

        <input type="text" name="email">

        <input name="coverArt" type="file"  multiple />

        <input name="profile" type="file"  multiple />

        <input type="file" name="songs"  multiple />

        <input type="file" name="videos"  multiple/>


        <button type="submit">Upload File</button>

 </form>

转到代码:


func FilePOST(w http.ResponseWriter, r *http.Request) error {

    fmt.Println("File Upload Endpoint Hit")

    mr, err := r.MultipartReader()

    if err != nil {

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

    }


    

    for {

        part, err := mr.NextPart()


        // This is OK, no more parts

        if err == io.EOF {

            break

        }


        // Some error

        if err != nil {

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

        }


转到服务器错误: 去运行 main.go [15:58:21] 现在在以下位置提供服务 www.localhost:3000 文件上传端点 命中信息[0009] POST /上传已过=“680.422μs” 主机 = 方法 = POST 路径=/上传查询= 2021/07/14 15:58:32 http: 恐慌服务 [::1]:62924: 运行时错误: 无效的内存地址或 nil 指针取消引用


青春有我
浏览 77回答 1
1回答

喵喵时光机

很难猜测你的代码在哪里恐慌。原因可能是您的程序在发生错误时继续执行。例如,如果创建文件失败,将死机,因为 为零。outfile.Close()outfile这两种方法都支持单个字段的多个文件。不同之处在于它们如何处理内存。流式处理版本从网络读取一小部分数据,并在您调用 时将其写入文件。另一个变体在您调用 时将所有数据加载到内存中,因此它需要与要传输的文件大小一样多的内存。您将在下面找到两种变体的工作示例。io.CopyParseMultiForm()流媒体变体:func storeFile(part *multipart.Part) error {&nbsp; &nbsp; name := part.FileName()&nbsp; &nbsp; outfile, err := os.Create("uploads/" + name)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; defer outfile.Close()&nbsp; &nbsp; _, err = io.Copy(outfile, part)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; return nil}func filePOST(w http.ResponseWriter, r *http.Request) error {&nbsp; &nbsp; fmt.Println("File Upload Endpoint Hit")&nbsp; &nbsp; mr, err := r.MultipartReader()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; part, err := mr.NextPart()&nbsp; &nbsp; &nbsp; &nbsp; // This is OK, no more parts&nbsp; &nbsp; &nbsp; &nbsp; switch {&nbsp; &nbsp; &nbsp; &nbsp; case errors.Is(err, io.EOF):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("done")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return nil&nbsp; &nbsp; &nbsp; &nbsp; case err != nil:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Some error&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch part.FormName() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "coverArt", "profile", "songs", "videos":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err := storeFile(part); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; http.HandleFunc("/upload", func(writer http.ResponseWriter, request *http.Request) {&nbsp; &nbsp; &nbsp; &nbsp; err := filePOST(writer, request)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.Error(writer, err.Error(), http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println("Error", err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; })&nbsp; &nbsp; if err := http.ListenAndServe(":8080", nil); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }}版本带有 ,它将数据读取到内存。ParseMultipartFormfunc storeFile(part *multipart.FileHeader) error {&nbsp; &nbsp; name := part.Filename&nbsp; &nbsp; infile, err := part.Open()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; defer infile.Close()&nbsp; &nbsp; outfile, err := os.Create("uploads/" + name)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; defer outfile.Close()&nbsp; &nbsp; _, err = io.Copy(outfile, infile)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; return nil}func FilePOST(w http.ResponseWriter, r *http.Request) error {&nbsp; &nbsp; fmt.Println("File Upload Endpoint Hit")&nbsp; &nbsp; if err := r.ParseMultipartForm(2 << 24); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; for _, fileType := range []string{"coverArt", "profile", "songs", "videos"} {&nbsp; &nbsp; &nbsp; &nbsp; uploadedFiles, exists := r.MultipartForm.File[fileType]&nbsp; &nbsp; &nbsp; &nbsp; if !exists {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; for _, file := range uploadedFiles {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err := storeFile(file); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return nil}func main() {&nbsp; &nbsp; http.HandleFunc("/upload", func(writer http.ResponseWriter, request *http.Request) {&nbsp; &nbsp; &nbsp; &nbsp; err := FilePOST(writer, request)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.Error(writer, err.Error(), http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println("Error", err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; })&nbsp; &nbsp; if err := http.ListenAndServe(":8080", nil); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go