【问题标题】:Multipart file field is unreadable多部分文件字段不可读
【发布时间】:2017-11-21 00:33:18
【问题描述】:

我正在尝试将照片上传到 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
    } 

【问题讨论】:

  • 您看到的错误是什么?
  • @CeriseLimón 我一次发送一个,就在这里我把它们写在一起,但我会尝试关闭作者,如果我设置了内容类型,我会收到一个错误的请求错误,让我尝试关闭作者跨度>
  • @YandryPozo {"errors":[{"code":38,"message":"media parameter is missing."}]}&{400 Bad Request 400 这是我得到的错误

标签: go twitter multipartform-data multipart form-fields


【解决方案1】:

更新:刚刚提到Twitter API Upload parameter。根据您的代码 sn-p 您正在使用两个字段 mediamedia_data。你只需要使用一个 -

  • 使用 base64 上传 -> 字段名称为 media_data
  • 使用原始上传 -> 字段名称为media

而且,您必须添加 Content-Type 标头。

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:在撰写答案时,@cerise-limón 在 30 秒的间隙内添加了评论,同时关闭了 @cerise-limón 提到的多部分编写器。


在评论中提问:

Twitter 接受 application/octet-stream,你可能不需要下面的方法。

使用用户提供的Content-Type 而不是application/octet-stream 添加多部分。基本上,您必须使用您的内容类型执行与便捷包装器相同的实现。

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

多部分包中escapeQuotes 的定义。

var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
func escapeQuotes(s string) string {
    return quoteEscaper.Replace(s)
}

【讨论】:

  • 哇,这就像我之前手动输入的 multipart/form-data 一样的魅力,但没有成功我猜是关键 vas writer.FormContentType() 谢谢。您是否有任何关于将文件类型设置为 image/png 而不是 application/octet-stream 的线索? @jeevatkm
  • 是的,你可以。我会将其添加到答案中。
  • 我只是从 createFormFile 的源代码中找到了它,无论如何感谢关闭作者
  • 我刚加了,反正你知道怎么做。
  • 但 Twitter 似乎仍然不喜欢它![](ws1.sinaimg.cn/large/006tNc79gy1fgq3tnmyrkj30je05uglo.jpg) 我还是收到了这个错误消息
猜你喜欢
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 2012-11-08
  • 2018-12-25
  • 2012-01-02
相关资源
最近更新 更多