【发布时间】:2021-11-12 21:49:18
【问题描述】:
我正在尝试通过 Facebook Graph API 上传本地视频。
这是官方文档:https://developers.facebook.com/docs/messenger-platform/reference/attachment-upload-api/
-F 'message={"attachment":{"type":"image", "payload":{"is_reusable":true}}}' \
-F 'filedata=@/tmp/shirt.png;type=image/png' \
"https://graph.facebook.com/v12.0/me/message_attachments?access_token=<PAGE_ACCESS_TOKEN>"
这是我的 Golang 代码:
func uploadVideoStream(c *Context, w http.ResponseWriter, r *http.Request) {
if err := r.ParseMultipartForm(MAXIMUM_PLUGIN_FILE_SIZE); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
m := r.MultipartForm
fileArray, ok := m.File["files"]
if !ok {
c.Err = model.NewAppError("uploadPlugin", "api.plugin.upload.no_file.app_error", nil, "", http.StatusBadRequest)
return
}
if len(fileArray) <= 0 {
c.Err = model.NewAppError("uploadPlugin", "api.plugin.upload.array.app_error", nil, "", http.StatusBadRequest)
return
}
file, err := fileArray[0].Open()
if err != nil {
c.Err = model.NewAppError("uploadPlugin", "api.plugin.upload.file.app_error", nil, "", http.StatusBadRequest)
return
}
defer file.Close()
// build a form body
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
_message := uploadVideoData{
Message: uploadVideoDataMessage{
Attachment: uploadVideoDataMessageAttachment{
Type: "video",
Payload: uploadVideoDataMessageAttachmentPayload{
IsReusable: true,
},
},
},
}
// add form fields
writer.WriteField("message", _message.Message.ToJson())
// add a form file to the body
fileWriter, err := writer.CreateFormFile("filedata", fileArray[0].Filename)
if err != nil {
c.Err = model.NewAppError("upload_video", "upload_video.error", nil, "", http.StatusBadRequest)
return
}
// copy the file into the fileWriter
_, err = io.Copy(fileWriter, file)
if err != nil {
c.Err = model.NewAppError("upload_video", "upload_video.error", nil, "", http.StatusBadRequest)
return
}
// Close the body writer
writer.Close()
reqUrl := "https://graph.facebook.com/v10.0/me/message_attachments"
token := "EAAUxUcj3C64BADxxsm70hZCXTMO0eQHmSpV..."
reqUrl += "?access_token=" + token
var netTransport = &http.Transport{
Dial: (&net.Dialer{
Timeout: 120 * time.Second,
}).Dial,
TLSHandshakeTimeout: 120 * time.Second,
ResponseHeaderTimeout: 120 * time.Second, // This will fixed the i/o timeout error
}
client := &http.Client{
Timeout: time.Second * 120,
Transport: netTransport,
}
req, _ := http.NewRequest("POST", reqUrl, body)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err1 := client.Do(req)
if err1 != nil {
fmt.Println("error1", err1)
c.Err = model.NewAppError("EditComment", err1.Error(), nil, "", http.StatusBadRequest)
return
} else {
defer resp.Body.Close()
var bodyBytes []byte
bodyBytes, _ = ioutil.ReadAll(resp.Body)
resp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
if resp.StatusCode != http.StatusOK {
fmt.Println("error2", resp.Body)
fbErr := facebookgraph.FacebookErrorFromJson(resp.Body)
c.Err = model.NewAppErrorFromFacebookError("EditComment", fbErr)
return
}
fmt.Println("UPLOAD VIDEO SUCCESS", resp.Body)
ReturnStatusOK(w)
}
}
这是上面代码的一些结构:
type uploadVideoDataMessageAttachmentPayload struct {
IsReusable bool `json:"is_reusable"`
}
type uploadVideoDataMessageAttachment struct {
Type string `json:"type"`
Payload uploadVideoDataMessageAttachmentPayload `json:"payload"`
}
type uploadVideoDataMessage struct {
Attachment uploadVideoDataMessageAttachment `json:"attachment"`
}
type uploadVideoData struct {
Message uploadVideoDataMessage `json:"message"`
}
func (o uploadVideoData) ToJson() string {
b, _ := json.Marshal(o)
return string(b)
}
func (o uploadVideoDataMessage) ToJson() string {
b, _ := json.Marshal(o)
return string(b)
}
Facebook 对于上述请求总是返回失败:
(#100) Upload attachment failure.
我正在尝试 CURL,并且成功了:
curl \
-F 'message={"attachment":{"type":"video", "payload":{"is_reusable":true}}}' \
-F 'filedata=@/home/cong/Downloads/123.mp4;type=video/mp4' \
"https://graph.facebook.com/v10.0/me/message_attachments?access_token=EAAUxUcj3C64BADxxsm70hZCXTMO0eQHmSp..."
{"attachment_id":"382840319882695"}%
谁能告诉我我遗漏了哪一部分,以及如何使我的请求等效于 CURL 工作?
非常感谢!
【问题讨论】:
-
根据我的经验,golang 不会添加任何额外的标题,而 curl 可能会。也许尝试使用
-v运行您的 curl 命令,看看是否有任何可能相关的额外标头。 -
您在上传响应中是否收到任何子错误代码?错误响应中的子代码可能更相关。
-
@sigkilled:子代码错误为 2018047:“上传附件失败。触发此错误的常见方法是提供的媒体类型与 URL 中提供的文件类型不匹配”。这似乎是我的问题,但我不确定如何设置媒体类型以匹配
标签: http go curl facebook-graph-api file-upload