Go中的多部分http请求

问题描述 投票:3回答:1

我正在尝试使用Go编写一个实用程序,通过向我们的服务器发出多部分http请求来验证和上载文件。一切似乎都没问题,除了文件没有到达服务器。进一步观察它看起来请求中的多部分是空的。代码和请求输出如下。我的Go代码中缺少什么?

代码:(我已经更改了URL ...)

package main

import (
    "net/http"
    "mime/multipart"
    "strings"
    "fmt"
    "io/ioutil"
    "io"
    "os"
    "bytes"
    "flag"
    "encoding/json"
)

var (
    filename = flag.String("filename", "", "file to upload")
    name = flag.String("name", "", "name to give file on server")
    username = flag.String("username", "", "username for authentication")
    password = flag.String("password", "", "password for authentication")
)

func main() {
    flag.Parse()

    // Create multipart
    var b bytes.Buffer
    w := multipart.NewWriter(&b)
    f, _ := os.Open(*filename) //open file to send
    defer f.Close()
    fw, err := w.CreateFormFile("file", *name) //give file a name
    if err != nil {
        fmt.Println(err)
    }
    if _, err :=  io.Copy(fw, f); err != nil { //copy the file to the multipart buffer
        fmt.Println(err)
    }
    w.Close()

    // print the head of the multipart data
    bs := b.Bytes()
    fmt.Printf("%+v\n\n", string(bs[:1000]))

    // Send authentication/login
    r, e := http.Post("https://mysite/login", "application/json", strings.NewReader(fmt.Sprintf("{\"username\":\"%s\",\"password\":\"%s\"}", *username, *password)))

    if e != nil {
        fmt.Println(e)
    } else {
        // Get the token from the body
        type Body struct {
            Token string
        }
        // convert json to get the token
        body, _ := ioutil.ReadAll(r.Body)
        bd := bytes.NewBuffer(body)
        dec := json.NewDecoder(bd)
        var m Body
        dec.Decode(&m)

        // Upload file
        req, err := http.NewRequest("POST", "https://mysite/api/apps", &b)
        if err != nil {
            fmt.Printf("%v\n", err)
        }
        req.Header.Set("Authentication", fmt.Sprintf("Bearer: %s", m.Token))
        req.Header.Set("Content-Type", w.FormDataContentType())
        client := &http.Client{}
        res, err := client.Do(req)
        if err != nil {
            fmt.Printf("%v\n", err)
        }
        // print status and request body
        fmt.Println(res.Status)
        fmt.Printf("%+v\n", res.Request)
    }
}

我打印的第一件事是字节缓冲区b,它包含多部分数据,从这里看起来一切都很好。 (这是一个xml文件)

--83451b003d8e5cc38c0e8f60ad318e522cad4818cf293745c84ec36d26d5
Content-Disposition: form-data; name="file"; filename="snapshot-162224-820-99"
Content-Type: application/octet-stream

<manifest>
  <projects>
    <project name=........

接下来,我打印请求的状态。

200 OK

然后我打印出请求结构,这里是我看到MultipartForm为空的地方。

&{Method:GET URL:https://mysite/home/ Proto: ProtoMajor:0 ProtoMinor:0 Header:map[Authentication:[Bearer: DY0LCJL0g] Content-Type:[multipart/form-data; boundary=83451b003d8e5cc38c0e8f60ad318e522cad4818cf293745c84ec36d26d5] Referer:[http://mysite/home/]] Body:<nil> GetBody:<nil> ContentLength:0 TransferEncoding:[] Close:false Host: Form:map[] PostForm:map[] MultipartForm:<nil> Trailer:map[] RemoteAddr: RequestURI: TLS:<nil> Cancel:<nil> Response:0xc42018a360 ctx:<nil>}
go
1个回答
0
投票

我非常怀疑服务器真的没有收到任何东西。具有零体的印刷体的行为预期并记录在http.Response

    // Request is the request that was sent to obtain this Response.
    // Request's Body is nil (having already been consumed).
    // This is only populated for Client requests.
    Request *Request

如果要调试发送的请求主体,则应使用模拟服务器或代理。

另一方面,您的代码尝试登录不起作用。它不维护登录信息的cookie,因此后来的请求无法使用它们。

© www.soinside.com 2019 - 2024. All rights reserved.