golang数据传输问题?

我要向一个接口post数据参数(我是golang中间层,接收前端的post请求,包装后发送给后端),但是数据参数有前台input传过来的files文件,类似这样

data={
    name //string
    sex  //string
    pic  //file
}

请问如何处理传输这些参数呢,之前定义的参数是map[string]string{},现在有files这种的不知道怎么处理了呢。。请求用了grequests这个包,求大神指点

具体就是向一个接口传递的参数包含文件的意思。。

阅读 4k
2 个回答

注意要点:

  • 理解普通文件上传,header 会是 multipart/form-data 类型,还有一些 application/json等等,具体用什么header由客户端和服务端统一协商决定.
  • 作为客户端,golangmime/multipart 包封装了文件上传的一些信息,可以很轻松的上传文件,增加字段
  • 作为服务端,如果发现有文件上传,应该首先解析文件即调用:r.ParseMultipartForm(maxSize),再从文件form中获取各个字段的值.
  • 你这边如果是文件类型是无法用map提交给服务端的,也应该使用mime/multipart类型去提交数据。
package main

import (
    "bytes"
    "fmt"
    "io"
    "io/ioutil"
    "mime/multipart"
    "net/http"
    "strings"
    "testing"
)

func main(t *testing.T) {
    s := new(s)
    http.ListenAndServe(":8086", s)
}

type s struct{}

func (s *s) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if r.RequestURI == "/upload" {
        upload(w, r)
        return
    }

    switch r.Method {
    case http.MethodPost:
        ct := r.Header.Get("Content-Type")
        switch {
        // 以下注释是 json逻辑和 form-urlencode 逻辑
        //case strings.HasPrefix(ct, "application/json"):
        //    // 处理json数据
        //    var data = make(map[string]interface{})
        //    err := json.NewDecoder(r.Body).Decode(&data)
        //    if err != nil {
        //        // 处理错误
        //    }
        //    fmt.Println(data)
        //case strings.HasPrefix(ct, "application/x-www-form-urlencoded"):
        //    // 表单数据
        //    r.ParseForm()
        //    fmt.Println(r.Form.Get("key"))

        // 文件上传逻辑.
        case strings.HasPrefix(ct, "multipart/form-data"): // 上传文件会带这个头.
            var maxSize int64 = 1024 * 1024 * 32           // 32MB 上传文件的最大值
            err := r.ParseMultipartForm(maxSize)           // 先解析文件
            if err != nil {
                // 错误处理
                return
            }
            sex := r.PostForm.Get("sex")               // 从表单中获取字段的值
            file, fileHeader, err := r.FormFile("pic") // 从表单中获取文件的信息
            if err != nil {
                // 错误处理
                return
            }
            _, _ = file, fileHeader
            // 把这个文件上传到指定的接口.
            bodyBuf := &bytes.Buffer{}
            bodyWriter := multipart.NewWriter(bodyBuf)
            fileWriter, err := bodyWriter.CreateFormFile("pic", fileHeader.Filename) // 添加一个文件字段,
            io.Copy(fileWriter, file)                                                // 写入这个文件
            contentType := bodyWriter.FormDataContentType()
            sexW, _ := bodyWriter.CreateFormField("sex") // 添加一个 sex 字段,
            sexW.Write([]byte(sex))                      // 写入这个字段
            bodyWriter.Close()

            resp, _ := http.Post("http://localhost:8086/upload", contentType, bodyBuf) // 模拟发送到本地的 /upload 接口

            b, _ := ioutil.ReadAll(resp.Body)
            defer resp.Body.Close()
            fmt.Println(string(b)) // 输出 /upload 接口的响应

            w.Write(b) // 输出到客户端.
        default:
            fmt.Println("content-Type is: ", ct)
        }
    }
}

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

    fmt.Println("upload ing...")
    var maxSize int64 = 1024 * 1024 * 32 // 32MB 上传文件的最大值
    err := r.ParseMultipartForm(maxSize)
    if err != nil {
        w.Write([]byte("上传错误" + err.Error()))
        return
    }
    sex := r.PostForm.Get("sex")
    _, fileHeader, err := r.FormFile("pic")

    resp := fmt.Sprintf("sex: %s, filename: %s ,fileSize: %d, ", sex, fileHeader.Filename, fileHeader.Size)
    w.Write([]byte(resp))
}
  • 启动
> go run main.go

客户端上传:

图片描述

服务端输出:

upload ing...
sex: 男, filename: 5.png ,fileSize: 20889, 
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题