多部分文件字段不可读
Multipart file field is unreadable
我正在尝试将照片上传到 Twitter。我创建了一个多部分编写器并使用该命名媒体创建了一个文件字段,但是当我将我的请求发送到 Twitter 时,它一直响应丢失的媒体字段。
我错过了什么吗?
这是我的代码
f, err := os.Open("/Users/nikos/Desktop/test.png")
errored:
if nil != err {
fmt.Println(err)
return
}
var img = new(bytes.Buffer)
enc := base64.NewEncoder(base64.StdEncoding, img)
_, err = io.Copy(enc, f)
if nil != err {
goto errored
}
body := new(bytes.Buffer)//Multipart body
writer := multipart.NewWriter(body)
cl, err := twitter.OauthClient.MakeHttpClient(&oauth.AccessToken{
Token: "xxx",
Secret: "yyy",
})
err = writer.WriteField("media_data", img.String())//base64 version of the image (i tried both binary and base64 versions neither will work)
if nil != err {
goto errored
}
part, err := writer.CreateFormFile("media", "test.png")//actual binary file multiparted and it is named media.
if nil != err {
goto errored
}
_, err = io.Copy(part, f)
if nil != err {
goto errored
}
req, err := http.NewRequest("POST",
"https://upload.twitter.com/1.1/media/upload.json",
body)
if nil != err {
goto errored
}
res, err := cl.Do(req)
if nil != err {
goto errored
}
//and twitter responds that there is no field attached named media
_, err = io.Copy(os.Stdout, res.Body)
fmt.Println(res)
if nil != err {
goto errored
}
更新:刚刚提到 Twitter API Upload parameter。根据您的代码片段,您同时使用了字段 media
和 media_data
。你必须只使用一个 -
- 使用 base64 上传 -> 字段名称是
media_data
- 使用原始上传 -> 字段名称是
media
而且,你必须添加 Content-Type
header.
req, err := http.NewRequest("POST",
"https://upload.twitter.com/1.1/media/upload.json",
body)
req.Header.Set("Content-Type", writer.FormDataContentType())
if err := writer.Close(); err != nil {
log.Println(err)
}
// Now fire the http request
PS:在撰写答案时,在 30 秒的间隔内,@cerise-limón 添加了评论,同时关闭了 @cerise-lim 提到的多部分编写器ón.
在评论中提问:
Twitter accepts application/octet-stream, you may not need below approach.
使用用户提供的 Content-Type
而不是 application/octet-stream
添加 multi-part。基本上,您必须使用 content-type.
执行与便利包装器相同的实现
writer := multipart.NewWriter(body)
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
escapeQuotes(fieldname), escapeQuotes(filename)))
h.Set("Content-Type", "image/png")
part, err := writer.CreatePart(h)
// use part same as before
来自 multiple-part 包的 escapeQuotes
的定义。
var quoteEscaper = strings.NewReplacer("\", "\\", `"`, "\\"")
func escapeQuotes(s string) string {
return quoteEscaper.Replace(s)
}
我正在尝试将照片上传到 Twitter。我创建了一个多部分编写器并使用该命名媒体创建了一个文件字段,但是当我将我的请求发送到 Twitter 时,它一直响应丢失的媒体字段。 我错过了什么吗? 这是我的代码
f, err := os.Open("/Users/nikos/Desktop/test.png")
errored:
if nil != err {
fmt.Println(err)
return
}
var img = new(bytes.Buffer)
enc := base64.NewEncoder(base64.StdEncoding, img)
_, err = io.Copy(enc, f)
if nil != err {
goto errored
}
body := new(bytes.Buffer)//Multipart body
writer := multipart.NewWriter(body)
cl, err := twitter.OauthClient.MakeHttpClient(&oauth.AccessToken{
Token: "xxx",
Secret: "yyy",
})
err = writer.WriteField("media_data", img.String())//base64 version of the image (i tried both binary and base64 versions neither will work)
if nil != err {
goto errored
}
part, err := writer.CreateFormFile("media", "test.png")//actual binary file multiparted and it is named media.
if nil != err {
goto errored
}
_, err = io.Copy(part, f)
if nil != err {
goto errored
}
req, err := http.NewRequest("POST",
"https://upload.twitter.com/1.1/media/upload.json",
body)
if nil != err {
goto errored
}
res, err := cl.Do(req)
if nil != err {
goto errored
}
//and twitter responds that there is no field attached named media
_, err = io.Copy(os.Stdout, res.Body)
fmt.Println(res)
if nil != err {
goto errored
}
更新:刚刚提到 Twitter API Upload parameter。根据您的代码片段,您同时使用了字段 media
和 media_data
。你必须只使用一个 -
- 使用 base64 上传 -> 字段名称是
media_data
- 使用原始上传 -> 字段名称是
media
而且,你必须添加 Content-Type
header.
req, err := http.NewRequest("POST",
"https://upload.twitter.com/1.1/media/upload.json",
body)
req.Header.Set("Content-Type", writer.FormDataContentType())
if err := writer.Close(); err != nil {
log.Println(err)
}
// Now fire the http request
PS:在撰写答案时,在 30 秒的间隔内,@cerise-limón 添加了评论,同时关闭了 @cerise-lim 提到的多部分编写器ón.
在评论中提问:
Twitter accepts application/octet-stream, you may not need below approach.
使用用户提供的 Content-Type
而不是 application/octet-stream
添加 multi-part。基本上,您必须使用 content-type.
writer := multipart.NewWriter(body)
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
escapeQuotes(fieldname), escapeQuotes(filename)))
h.Set("Content-Type", "image/png")
part, err := writer.CreatePart(h)
// use part same as before
来自 multiple-part 包的 escapeQuotes
的定义。
var quoteEscaper = strings.NewReplacer("\", "\\", `"`, "\\"")
func escapeQuotes(s string) string {
return quoteEscaper.Replace(s)
}