Can I post with Content-Type: multipart/form-data

2020-06-23 07:48发布

How do I POST to an API with Content-Type: multipart/form-data, []byte parameters and string arguments? I have tried, but it is failing.

Error message:

details: "[301 301 Moved Permanently]<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html>\r\n301 Moved Permanently\r\n<body bgcolor=\"white\">\r\n301 Moved Permanently\r\n<p>The requested resource has been assigned a new permanent URI.</p >\r\n<hr/>Powered by Tengine/2.1.0</body>\r\n</html>\r\n"

Go code:

func NewPost2(url string) ([]byte, error) {
    m := make(map[string]interface{}, 0)
    m["fileName"] ="good"
    m["name"] = Base64ToByte("/9j/4AAQSkZJRgABAQEAeAB4AAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDHooor+wD+Zz//2Q==")
b, _ := json.Marshal(m)

    httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(b))
    httpReq.Header.Set("Content-Type", "multipart/form-data;charset=UTF-8")

    client := &http.Client{}
    resp, err := client.Do(httpReq)
    if err != nil {
        return nil, err
    }

    defer resp.Body.Close()

    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
        b, _ := ioutil.ReadAll(resp.Body)
        return nil, fmt.Errorf("[%d %s]%s", resp.StatusCode, resp.Status, string(b))
    }

    respData, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    return respData, nil
}

标签: http go
2条回答
小情绪 Triste *
2楼-- · 2020-06-23 08:17

On a 301 response, the new url is specified in the headers of the response, not its body

(see https://en.wikipedia.org/wiki/HTTP_301)

try printing :

resp.Header["Location"]

If you have this error as a final response, this also means that the http.Client chose to not follow this redirection.

The doc says that the dafult policy for a Client is to follow up to 10 redirects.

In order to debug redirects, you can write your own CheckRedirect function, which can for instance print the sequence of urls

查看更多
对你真心纯属浪费
3楼-- · 2020-06-23 08:25

Now, I am very happy with the mood to share my solution

func NewPostFile(url string, paramTexts map[string]interface{}, paramFile FileItem) ([]byte, error) {
// if paramFiles ==nil {
//  return NewPost(url,paramTexts,header,transport)
// }

bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)

for k, v := range paramTexts {
    bodyWriter.WriteField(k, v.(string))
}
fileWriter, err := bodyWriter.CreateFormFile(paramFile.Key, paramFile.FileName)
if err != nil {
    fmt.Println(err)
    //fmt.Println("Create form file error: ", error)
    return nil, err
}
fileWriter.Write(paramFile.Content)
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
fmt.Println(bodyBuf.String())

resp, err := http.Post(url, contentType, bodyBuf)
if err != nil {
    return nil, err
}
defer resp.Body.Close()
fmt.Println(resp)

if resp.StatusCode < 200 || resp.StatusCode >= 300 {
    b, _ := ioutil.ReadAll(resp.Body)
    return nil, fmt.Errorf("[%d %s]%s", resp.StatusCode, resp.Status, string(b))
}
respData, err := ioutil.ReadAll(resp.Body)
if err != nil {
    return nil, err
}
fmt.Println(string(respData))
return respData, nil

}

type FileItem struct {
Key      string //image_content
FileName string //test.jpg
Content  []byte //[]byte

}

查看更多
登录 后发表回答