【问题标题】:How do you parse both a file and JSON data out of one HTTP request with Go?如何使用 Go 从一个 HTTP 请求中同时解析文件和 JSON 数据?
【发布时间】:2015-03-23 01:51:59
【问题描述】:

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

HTTP 请求

内容配置:表单数据;名称=“文件”; filename="家长手册.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)
}

【问题讨论】:

    标签: angularjs http go request


    【解决方案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) {
        mr, err := r.MultipartReader()
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
    
        doc := Doc{}
        for {
            part, err := mr.NextPart()
    
            // This is OK, no more parts
            if err == io.EOF {
                break
            }
    
            // Some error
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
    
            // PDF 'file' part
            if part.FormName() == "file" {
                doc.Url = part.FileName()
                fmt.Println("URL:", part.FileName())
                outfile, err := os.Create("./docs/" + part.FileName())
                if err != nil {
                    http.Error(w, err.Error(), http.StatusInternalServerError)
                    return
                }
                defer outfile.Close()
    
                _, err = io.Copy(outfile, part)
                if err != nil {
                    http.Error(w, err.Error(), http.StatusInternalServerError)
                    return
                }
            }
    
            // JSON 'doc' part
            if part.FormName() == "doc" {
                jsonDecoder := json.NewDecoder(part)
                err = jsonDecoder.Decode(&doc)
                if err != nil {
                    http.Error(w, err.Error(), http.StatusInternalServerError)
                    return
                }
                fmt.Println(doc.Title, doc.Url, doc.Cat, doc.Date)
            }
        }
    
        doc.Id = len(docs) + 1
        err = s.db.Insert(&doc)
        checkErr(err, "Insert failed")
    
        s.Ren.JSON(w, http.StatusOK, &doc)
    }
    

    【讨论】:

    • 感谢您花时间向我解释。现在更有意义了。我已经坚持了一个多星期。让我头疼不已,谢谢!!!
    • 获取错误为'http:ParseMultipartForm处理的多部分'
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    相关资源
    最近更新 更多