Golang中如何获取文件上传字段名

Golang中如何获取文件上传字段名 如果使用 Go 监控服务器 POST 请求,在不知道字段名的情况下如何保存文件上传?!

在这行代码中:

file, handler, err := r.FormFile("uploadfile")

如果我不知道字段名:“uploadfile”,该如何获取该文件并保存?!

4 回复

更多关于Golang中如何获取文件上传字段名的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


r 是一个 http.Request 吗?

终于我让它正常工作了。首先我使用以下函数检测请求是否为multipart类型:

func isMultipart(r *http.Request) bool {
  ct := r.Header.Get("Content-Type")
  ctm := strings.Split(ct, ";")

  if ctm[0] == "multipart/form-data" {
    return true
  }

  return false
}

主要功能是将上传的文件保存到TEST目录,不指定特定的上传字段名:

if isMultipart(r) {
  err := r.ParseMultipartForm(1 << 20)

  if err == nil {
    formData := r.MultipartForm
    keys := reflect.ValueOf(formData).Elem()
    // Field()中的第二个map是文件字段
    // 第一个map是所有输入字段,不包括文件上传字段
    uloadFileFieldMaps := keys.Field(1)
    if uloadFileFieldMaps.Kind() == reflect.Map {
      uploadFieldNames := uloadFileFieldMaps.MapKeys()
      for _, uploadFieldName := range uploadFieldNames {
        file, handler, err := r.FormFile(uploadFieldName.String())

        if err != nil {
          fmt.Println(err)
          return
        }
        defer file.Close()
        f, err := os.OpenFile("./test/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
        if err != nil {
          fmt.Println(err)
          return
        }
        defer f.Close()
        io.Copy(f, file)
      }
    }
  }
}

希望对某人有所帮助

在Go中处理未知字段名的文件上传时,可以通过解析multipart表单来遍历所有文件字段。以下是完整的解决方案:

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    // 解析multipart表单,限制最大内存使用
    err := r.ParseMultipartForm(32 << 20) // 32MB
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // 遍历表单中的所有文件字段
    for fieldName, fileHeaders := range r.MultipartForm.File {
        for _, fileHeader := range fileHeaders {
            fmt.Printf("发现文件字段: %s, 文件名: %s\n", fieldName, fileHeader.Filename)
            
            // 打开上传的文件
            file, err := fileHeader.Open()
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            defer file.Close()

            // 创建目标文件
            dst, err := os.Create("./uploads/" + fileHeader.Filename)
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            defer dst.Close()

            // 复制文件内容
            if _, err := io.Copy(dst, file); err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }

            fmt.Printf("文件 %s 保存成功\n", fileHeader.Filename)
        }
    }

    w.Write([]byte("文件上传处理完成"))
}

func main() {
    http.HandleFunc("/upload", uploadHandler)
    http.ListenAndServe(":8080", nil)
}

另一种更简洁的方法是直接使用r.MultipartReader()

func uploadHandler2(w http.ResponseWriter, r *http.Request) {
    reader, err := r.MultipartReader()
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    for {
        part, err := reader.NextPart()
        if err == io.EOF {
            break
        }
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        // 检查是否是文件字段
        if part.FileName() != "" {
            fmt.Printf("发现文件字段: %s, 文件名: %s\n", part.FormName(), part.FileName())
            
            dst, err := os.Create("./uploads/" + part.FileName())
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            defer dst.Close()

            if _, err := io.Copy(dst, part); err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }

            fmt.Printf("文件 %s 保存成功\n", part.FileName())
        }
    }

    w.Write([]byte("文件上传处理完成"))
}

这两种方法都能处理未知字段名的文件上传,第一种方法更适合处理多个文件,第二种方法则提供了更细粒度的控制。

回到顶部