I'm following this official Docs: https://developers.facebook.com/docs/messenger-platform/reference/attachment-upload-api/ to try to send a message with video attachment. What I've tried:
//...
api.BaseRoutes.Conversation.Handle("/video", api.ApiSessionRequired(sendVideo)).Methods("POST")
//...
func sendVideo(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequirePageId().RequireConversationId()
if c.Err != nil {
return
}
conversation, getErr := c.App.GetConversation(c.Params.ConversationId)
if getErr != nil {
c.Err = getErr
return
}
if err := r.ParseMultipartForm(25*1024*1024); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// detect file header
f, _, err := r.FormFile("files")
// Create a buffer to store the header of the file in
fileHeader := make([]byte, 512)
// Copy the headers into the FileHeader buffer
if _, err := f.Read(fileHeader); err != nil {
}
// set position back to start.
if _, err := f.Seek(0, 0); err != nil {
}
_fileType := http.DetectContentType(fileHeader)
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)
// add form fields
writer.WriteField("message", "{\"attachment\":{\"type\":\"video\", \"payload\":{\"is_reusable\":true}}}\")
//fileWriter, err := CreateFormFile(writer, "filedata", fileArray[0].Filename)
// 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 := c.App.Session().GetPageToken(c.Params.PageId)
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 {
c.Err = model.NewAppError("send_video", 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 {
fbErr := facebookgraph.FacebookErrorFromJson(resp.Body)
fmt.Println("__ERROR___", fbErr)
c.Err = model.NewAppErrorFromFacebookError("send_video", fbErr)
return
}
// Do what ever we want with attachment_id result
}
ReturnStatusOK(w)
}
But always failed with error from Facebook:
{
"error": {
"message": "(#100) Upload attachment failure.",
"type": "OAuthException",
"code": 100,
"error_subcode": 2018047,
"fbtrace_id": "A2hkvhTQlmA98XmcrPvSy8O"
}
}
The error subcode is: 2018047 according to Facebook docs:
Upload attachment failure. A common way to trigger this error is that the provided media type does not match type of file provided int the URL
I also try via cURL and everything's OK:
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"}%
If I change "video" to "file", upload is success:
writer.WriteField("message", "{\"attachment\":{\"type\":\"file\", \"payload\":{\"is_reusable\":true}}}\")
But Facebook will send video as "file attachment" (can not view as video, must download to view). That's not what I want.
Can any one tell me how to fix this problem? Thank you very much!