公众号开发,使用 上传图文消息内的图片获取 URL 这个 API,文档提示这个 api 接收两个参数,一个是 token,另一个是 media,其中 media 是:form-data 中媒体文件标识,有 filename、filelength、content-type 等信息。
用这个 api 遇到了两个问题:
{ errcode: 41005, errmsg: 'media data missing hint: [NM04491543]' }
{ errcode: 40005, errmsg: 'invalid file type hint: [2okiFa07923938] rid: 6003e838-2424bdb4-6a2ee294' }
第一个问题现在看来,是少了 filename、filelength、content-type 这些信息,第二个问题可能是少了 content-type。
先看看有问题的例子,如果 form.append()
少了后面的 options 就会提示 41005,如果有 options,但只有 filename 没有 contentType 会提示 40005。
const got = require("got");
const FormData = require("form-data");
const buffer = ...; //从网络获取图片,返回 buffer
const form = new FormData();
form.append("media", buffer, {
filename: "image",
});
const url = `https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=${token}`;
const result = await got
.post(url, { body: form })
.then((res) => res.body)
.then((res) => JSON.parse(res));
但是,如果像下面这样写,就不需要提供 file* 信息,因为 form-data
其实是可以从多种 stream 中自动获取这些信息的:
Form-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request) 文档
const got = require("got");
const FormData = require("form-data");
const fs = require("fs");
const filePath = "image.png";
const form = new FormData();
form.append("media", fs.createReadStream(filePath));
const url = `https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=${token}`;
const result = await got
.post(url, { body: form })
.then((res) => res.body)
.then((res) => JSON.parse(res));
第一个例子我从网络拿到 buffer,然后根据 buffer 创建 FormData
,第二个例子是直接读取本地文件,用拿到的 stream 创建 FormData
,前者无法自动获取完整的 filename、filelength、content-type 等信息,但是后者可以。
第一个例子改成下面这样应该就没问题,既然 form-data
无法从 buffer 中拿到 filename、filelength、content-type 这些信息,那就用 file-type
获取这些信息,然后手动提供给 form-data
:
const got = require("got");
const FormData = require("form-data");
const { fromBuffer } = require("file-type");
const buffer = ...; //从网络获取图片,返回 buffer
const mime = await fromBuffer(buffer).then(res => res.mime);
const ext = await fromBuffer(buffer).then(res => res.ext);
const form = new FormData();
form.append("media", buffer, {
contentType: mime,
filename: `image.${ext}`,
});
const url = `https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=${token}`;
const result = await got
.post(url, { body: form })
.then((res) => res.body)
.then((res) => JSON.parse(res));
小程序 wx.uploadFile()
也有 formData 的使用,security.imgSecCheck
也是。
相关文章: