logo科技微讯

公众号开发上传图片 41005 报错

作者:科技微讯
日期:2021-01-17
📝 笔记

公众号开发,使用 上传图文消息内的图片获取 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 也是。


相关文章:

donation赞赏
thumbsup0
thumbsdown0
暂无评论