Изображение Golang POST и текстовое поле с данными multipart / form

Да, я нашел ответы:

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

данные Golang POST с использованием Content-Type multipart / form- данные

Составное программирование файлов HTTP-POST на языке Go

И ответы бесполезны, потому что я получаю ошибку с multipart.NewWriter. Моя версия 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)

}

Файл загружается отлично, но я не могу получить данные из текстового поля. Я пытаюсь понять, в чем разница между простой формой с полями и составной формой, и как я могу получать данные из полей

Спасибо и привет


person Ivan R    schedule 27.11.2014    source источник
comment
Возможно, вы могли бы сжать свой код до того, что на самом деле не работает. Я понимаю, что загрузка файлов работает, но не ввод в текстовое поле. Но ваш код Go никогда не пытается читать данные textarea? Что не так с Request.Form или Request.FormValue?   -  person Volker    schedule 27.11.2014
comment
@ Volker q.Formvalue (aboutMySelf) выводит пустую строку. Я думаю, что в многостраничной форме мне нужно что-то еще, если я хочу получить данные из текстового поля   -  person Ivan R    schedule 27.11.2014
comment
Убедитесь, что вы сделали q.Formvalue (aboutMySelf) после вызова ParseMultipartForm.   -  person Volker    schedule 27.11.2014
comment
@Volker Да! ParseMultipartForm (). Спасибо!   -  person Ivan R    schedule 27.11.2014


Ответы (1)


Вы можете получить multipart.Part из multipart.Reader. 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
}
person Alexander Jeyaraj    schedule 25.10.2019