带有多部分/表单数据的 golang POST 图像和文本字段



是的,我找到了答案:

http://matt.aimonetti.net/posts/2013/07/01/golang-multipart-file-upload-example/

使用内容类型多部分/表单数据的 golang POST 数据

用 Go 语言进行 HTTP-POST 文件多部分编程

答案没有帮助,因为我在多部分时遇到错误。新作家。我的 go lang 版本 1.3.3

我正在尝试发送一些带有表单(templates/form.html)的文本数据和图像

    <form enctype="multipart/form-data" method="POST">
      <div class="row">
        <div class="large-6 columns">
          <label>Image
            <input type="file" name="Image" class="button"/>
          </label>
        </div>
     </div>
    <div class="row">
        <div class="large-12 columns">
          <label>About Me
            <textarea type="text" name="aboutMySelf" class="aboutMySelf"></textarea>
          </label>
        </div>
    </div>
</form>

我的 Go 方法是这样的:

package main
import (
    "fmt"
    "html/template"
    "io"
    "log"
    "net/http"
    "net/textproto"
    "os"
    "reflect"
    "time"
    "github.com/gorilla/mux"
    "github.com/gorilla/schema"
)

func render(w http.ResponseWriter, tmpl string, context map[string]interface{}) {
    tmpl_list := []string{fmt.Sprintf("templates/%s.html", tmpl)}
    t, err := template.ParseFiles(tmpl_list...)
    if err != nil {
        log.Print("template parsing error: ", err)
    }
    err = t.Execute(w, context)
    if err != nil {
        log.Print("template executing error: ", err)
    }
}
    type FileHeader struct {
        Filename string
        Header   textproto.MIMEHeader
        // contains filtered or unexported fields
    }
     func uploadImage(q *http.Request, nameInForm string) {
        q.ParseMultipartForm(32 << 20)
        file, _, err := q.FormFile(nameInForm)
        if err != nil {
            fmt.Println(err)
        }
        defer file.Close()
        f, err := os.OpenFile("./static/uploadimages/"+handler.Filename+".jpg", os.O_WRONLY|os.O_CREATE, 0666)
        if err != nil {
            fmt.Println(err)
        }
        defer f.Close()
        io.Copy(f, file)
    }
func main() {
    rtr := mux.NewRouter()

    //ADMIN SECTION
    rtr.HandleFunc("/myself", myself).Methods("GET")
    rtr.HandleFunc("/myself", myselfP).Methods("POST")

    rtr.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))
    http.Handle("/", rtr)
    log.Println("Listening...")
    http.ListenAndServe(":3000", nil)
}
func myself(w http.ResponseWriter, q *http.Request) {
    render(w,"form",nil)
}
func myselfP(w http.ResponseWriter, q *http.Request) {
    err := q.ParseForm()
    if err != nil {
        // Handle error
        fmt.Println(err)
    }
    uploadImage(q, "Image")

    http.Redirect(w, q, "/myself", http.StatusFound)
}

文件上传完美,但我无法从文本区域获取数据。我正在尝试了解带有字段的简单表单和多部分表单之间的区别,以及如何从字段中获取数据

感谢和问候

你可以得到一个多部分。部分来自多部分。读者。如果参数不是文件,则 Part.FileName() 将为空。您可以通过调用 r.MultipartReader() 来获取读取器。获得阅读器后,以下代码将为您提供文件数组和其他字段的映射。

func ReadFormData(mr *multipart.Reader) ([]FileParam, map[string]interface{}, error) {
    var part *multipart.Part
    var err error
    paramFiles := []FileParam{}
    paramTexts := map[string]interface{}{}
    for {
        if part, err = mr.NextPart(); err != nil {
            if err != io.EOF { //io.EOF error means reading is complete
                return paramFiles, paramTexts, fmt.Errorf(" error reading multipart request: %+v", err)
            }
            break
        }
        if part.FileName() != "" {
            content, err := readFileParam(part)
            if err != nil {
                return paramFiles, paramTexts, fmt.Errorf(" error reading file param %s: %+v", part.FileName, err)
            }
            fileItem := FileParam{
                Key:      "configFiles",
                FileName: part.FileName(),
                Content:  content,
            }
            paramFiles = append(paramFiles, fileItem)
        } else {
            name := part.FormName()
            value := readValueFromFormData(part)
            paramTexts[name] = value
        }
    }
    return paramFiles, paramTexts, nil
}
func readValueFromFormData(part *multipart.Part) string {
    buf := new(bytes.Buffer)
    buf.ReadFrom(part)
    return buf.String()
}
func readFileParam(part *multipart.Part) ([]byte, error) {
    content := []byte{}
    uploaded := false
    var err error
    for !uploaded {
        chunk := make([]byte, 4096)
        if _, err = part.Read(chunk); err != nil {
            if err != io.EOF {
                return nil, fmt.Errorf(" error reading multipart file %+v", err)
            }
            uploaded = true
        }
        content = append(content, chunk...)
    }
    return content, nil
}
type FileParam struct {
    Key      string
    FileName string
    Content  []byte
}

最新更新