WhatsApp Cloud API上传报错:MIME类型错误引发invalid_request
我用Axios给WhatsApp Cloud API上传.png图片时遇到问题,明明已经把表单数据的内容类型设为image/png,但一直收到WhatsApp返回的invalid_request错误,说参数“file”必须是指定MIME类型的文件,实际收到的是application/octet-stream。
错误信息
OAuth 'Facebook Platform' 'invalid_request' '(#100) Param file must be a file with one of the following types:
audio/aac, audio/mp4, audio/mpeg, audio/amr, audio/ogg, audio/opus, application/vnd.ms-powerpoint, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/pdf, text/plain, application/vnd.ms-excel, image/jpeg, image/png, image/webp, video/mp4, video/3gpp. Received file of type 'application/octet-stream'
请求截图

原代码
(async () => { const formData = new FormData(); formData.append("messaging_product", "whatsapp"); formData.append("type", "image/png"); const stream = await streamToBlob( fs.createReadStream( "/filepath" ) ); formData.append("file", stream); console.log("formData", formData); let config = { method: "post", maxBodyLength: Infinity, url: `https://graph.facebook.com/v18.0/${phoneNumberId}/media`, headers: { Authorization: `Bearer ${token}`, "Content-Type": "multipart/form-data;image/png", }, data: formData, }; axios .request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); }); })();
问题原因及解决办法
核心问题
- 手动设置Content-Type破坏了表单结构:你在请求头里手动写了
"Content-Type": "multipart/form-data;image/png",这会覆盖FormData自动生成的boundary分隔符,导致服务器无法正确解析表单内容,同时也没正确传递文件的MIME类型。 - 文件添加时未指定类型和文件名:将Blob对象添加到FormData时,只传了流对象,没有指定文件名(带后缀)和MIME类型,WhatsApp API无法识别文件格式,默认判定为
application/octet-stream。
修改后的代码
(async () => { const formData = new FormData(); formData.append("messaging_product", "whatsapp"); formData.append("type", "image/png"); // 直接用文件流添加,同时指定文件名和MIME类型 const fileStream = fs.createReadStream("/filepath"); formData.append("file", fileStream, { filename: "target-image.png", // 必须带.png后缀 contentType: "image/png" }); let config = { method: "post", maxBodyLength: Infinity, url: `https://graph.facebook.com/v18.0/${phoneNumberId}/media`, headers: { Authorization: `Bearer ${token}`, // 移除手动设置的Content-Type,用FormData自动生成的头信息 ...formData.getHeaders() }, data: formData, }; axios .request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); }); })();
如果仍需使用streamToBlob转换后的对象,修改文件添加逻辑即可:
formData.append("file", stream, { filename: "target-image.png", contentType: "image/png" });
关键要点
- 永远不要手动设置
multipart/form-data类型的请求头,使用formData.getHeaders()让FormData自动生成包含正确boundary的头信息 - 添加文件到FormData时,必须明确指定文件名(带对应后缀)和
contentType,确保服务器能正确识别文件类型
内容的提问来源于stack exchange,提问作者Omkar Patne

