http - 将文件上传转发到其他服务器
问题描述
我正在尝试通过 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 工作?
非常感谢!
解决方案
感谢@sigkilled 按照他的建议,我检查了 subcode_error 并发现此错误是由我设置的文件类型之间的匹配文件类型未命中引起的:
_message := uploadVideoData{
Message: uploadVideoDataMessage{
Attachment: uploadVideoDataMessageAttachment{
Type: "video",
Payload: uploadVideoDataMessageAttachmentPayload{
IsReusable: true,
},
},
},
}
以及 Facebook 服务器检测到的文件类型。然后我将“视频”更改为“文件”并成功!
非常感谢,你教给我的不仅仅是这个问题!
推荐阅读
- java - Java 应用程序如何知道是否创建了新的 JIRA 票证?
- c# - geckodriver 找不到实体问题
- python - 无法将字符串格式的日期转换为日期时间对象
- angular - 没有路由器插座的延迟加载的角度模块不起作用
- php - 如果会话已经开始,如何忽略会话?
- java - java8 orElse(null.getValue()) 怎么处理
- regex - 用于查找某些单词的正则表达式
- css - 如何在反应组件中调试 webpacker CSS 加载问题?
- openedge - 我如何理解 FOR EACH 和 FOR FIRST 之间的区别?
- php - 我使用唯一验证时出现重复输入错误