如何使用 Go 从一个 HTTP 请求中解析文件和 JSON 数据?

我一直在试图弄清楚如何从 Angularjs 前端的一个 http 请求表单中解析 PDF 文档和 JSON 数据。请求有效载荷是


HTTP 请求


内容配置:表单数据;名称=“文件”;filename="Parent Handbook.pdf" 内容类型:application/pdf


内容配置:表单数据;名称=“文档”


{"title":"test","cat":"test cat","date":20142323}


“file”是pdf,“doc”是我要解析的json数据。


我的处理程序可以很好地解析和保存文件,但无法从 Json 中获取任何内容。有任何想法吗?


func (s *Server) PostFileHandler(w http.ResponseWriter, r *http.Request) {

    const _24K = (1 << 20) * 24

    err := r.ParseMultipartForm(_24K)

    if err != nil {

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

        return

    }

    doc := Doc{}

    jsonDecoder := json.NewDecoder(r.Body)

    fmt.Println(r.Body)

    err = jsonDecoder.Decode(&doc)

    if err != nil {

        fmt.Println(err.Error())

    }

    fmt.Println(doc.Title, doc.Url, doc.Cat, doc.Date)

    doc.Id = len(docs) + 1

    err = s.db.Insert(&doc)

    checkErr(err, "Insert failed")


    // files := m.File["myFile"]

    for _, fheaders := range r.MultipartForm.File {

        for _, hdr := range fheaders {

            var infile multipart.File

            infile, err = hdr.Open()

            // defer infile.Close()

            if err != nil {

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

                return

            }

            doc.Url = hdr.Filename

            fmt.Println(hdr.Filename)

            var outfile *os.File

            outfile, err = os.Create("./docs/" + hdr.Filename)

            // defer outfile.Close()

            if err != nil {

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

                return

            }

            _, err = io.Copy(outfile, infile)

            if err != nil {

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

                return

            }


        }

    }

    s.Ren.JSON(w, http.StatusOK, &doc)

    // http.Error(w, "hit file server", http.StatusOK)

}


森林海
浏览 354回答 1
1回答

猛跑小猪

在您的示例中,您试图读取 r.Body 就好像它是从请求的 PDF 部分中剥离出来的一样,但事实并非如此。您需要分别处理 PDF 和 JSON 这两个部分。使用http.(*Request).MultipartReader()。r.MultipartReader() 将返回mime/multipart.Reader对象,因此您可以使用r.NextPart()函数迭代各个部分并分别处理每个部分。所以你的处理函数应该是这样的:func (s *Server) PostFileHandler(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; mr, err := r.MultipartReader()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; http.Error(w, err.Error(), http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; doc := Doc{}&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; if err == io.EOF {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // Some error&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.Error(w, err.Error(), http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // PDF 'file' part&nbsp; &nbsp; &nbsp; &nbsp; if part.FormName() == "file" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doc.Url = part.FileName()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("URL:", part.FileName())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; outfile, err := os.Create("./docs/" + part.FileName())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.Error(w, err.Error(), http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer outfile.Close()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _, err = io.Copy(outfile, part)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.Error(w, err.Error(), http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // JSON 'doc' part&nbsp; &nbsp; &nbsp; &nbsp; if part.FormName() == "doc" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; jsonDecoder := json.NewDecoder(part)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; err = jsonDecoder.Decode(&doc)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.Error(w, err.Error(), http.StatusInternalServerError)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(doc.Title, doc.Url, doc.Cat, doc.Date)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; doc.Id = len(docs) + 1&nbsp; &nbsp; err = s.db.Insert(&doc)&nbsp; &nbsp; checkErr(err, "Insert failed")&nbsp; &nbsp; s.Ren.JSON(w, http.StatusOK, &doc)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go