微信订阅号-永久素材上传和获取
发布于 2021-01-15 16:00
对于常用的素材,开发者可通过本接口上传到微信服务器,永久使用。新增的永久素材也可以在公众平台官网素材管理模块中查询管理。
请注意:
1、最近更新:永久图片素材新增后,将带有URL返回给开发者,开发者可以在腾讯系域名内使用(腾讯系域名外使用,图片将被屏蔽)。
3、素材的格式大小等要求与公众平台官网一致:
图片(image): 10M,支持bmp/png/jpeg/jpg/gif格式
语音(voice):2M,播放长度不超过60s,mp3/wma/wav/amr格式
视频(video):10MB,支持MP4格式
缩略图(thumb):64KB,支持JPG格式
4、图文消息的具体内容中,微信后台将过滤外部的图片链接,图片url需通过"上传图文消息内的图片获取URL"接口上传图片获取。
我们将使用co-wechat-api这个库提供的方法来完成
1.上传永久素材-图片(image)语音(voice)缩略图(thumb)
还是同样的套路router->controller->service
app/router.js
controller/auth.js
async uploadMaterial() {
const { ctx, service } = this;
const data = ctx.request.query;
const res = await service.auth.uploadMaterial(data);
ctx.body = res;
}
service/auth.js
const Service = require("egg").Service;
const toArray = require("stream-to-array");
const WeChatAPI = require("co-wechat-api");
const fs = require("fs");
const path = require("path");
class AuthService extends Service {
constructor(ctx) {
super(ctx);
this.api = new WeChatAPI('appId', 'AppSecret');
}
// 上传永久素材有图片(image)、语音(voice)、和缩略图(thumb)
async uploadMaterial(params) {
const { ctx, app, service } = this;
params = {
...params,
type: params.type || "image",
};
// 前端传递参数用formData数据
// const formData = new FormData();
// formData.append(file); // file即选择的文件 将formData发送到后台
// 后台通过文件流获取数据
const stream = await ctx.getFileStream();
const parts = await toArray(stream);
const buf = Buffer.concat(parts);
const fileName = stream.filename;
const filePath = path.resolve(__dirname, "../../media", fileName); // 文件存储的路径
// 将文件保存到服务端-必须要保存
// co-wechat-api 库要求我们传递文件的路径。所以这个文件路径必须要有这个文件才能上传成功
fs.writeFile(filePath, buf, async (err) => {
if (err) {
console.log(err);
}
});
const result = await this.api.uploadMaterial(filePath, params.type);
/* 正常情况下需要往自己的数据库存储以下4个字段:
type: 可取值 image,voice,thumb
fileName, 文件名称 可从stream.filename获取【2.png】
media_id, 媒体id 由微信返回result.media_id - 用于获取上传的永久素材
mimeType, 文件后缀名 可从stream.mimeType获取 - 如果是图片【image/png】用于返回前端base64格式做拼接
*/
return {
data: result,
msg: params.type + "永久素材上传成功",
};
}
}
module.exports = AuthService;
上传图片实例:
上传缩略图实例:
总结:图片,语音,缩略图上传成功后会返回:media_id,url
2.上传永久素材-视频(video)
app/router.js
controller/auth.js
async uploadMaterial() {
const { ctx, service } = this;
const data = ctx.request.query;
const res = await service.auth.uploadVideoMaterial(data);
ctx.body = res;
}
service/auth.js
const Service = require("egg").Service;
const toArray = require("stream-to-array");
const WeChatAPI = require("co-wechat-api");
const fs = require("fs");
const path = require("path");
class AuthService extends Service {
constructor(ctx) {
super(ctx);
this.api = new WeChatAPI('appId', 'AppSecret');
}
// 上传永久素材-video
// params 包含 title 和 introduction 两个字段
async uploadVideoMaterial(params) {
const { ctx, app, service } = this;
// 前端传递参数用formData数据
// const formData = new FormData();
// formData.append(file); // file即选择的文件 将formData发送到后台
// 后台通过文件流获取数据
const stream = await ctx.getFileStream();
const parts = await toArray(stream);
const buf = Buffer.concat(parts);
const fileName = stream.filename;
const filePath = path.resolve(__dirname, "../../media", fileName); // 文件存储的路径
// 将文件保存到服务端-必须要保存
// co-wechat-api 库要求我们传递文件的路径。所以这个文件路径必须要有这个文件才能上传成功
fs.writeFile(filePath, buf, async (err) => {
if (err) {
console.log(err);
}
});
const result = await this.api.uploadVideoMaterial(filePath, params);
return {
data: result,
msg: "视频永久素材上传成功",
};
}
}
module.exports = AuthService;
上传视频实例:
总结:视频上传成功后会返回:media_id
3.上传永久素材-图文(news)
app/router.js
controller/auth.js
async uploadNewsMaterial() {
const { ctx, service } = this;
const data = ctx.request.body; // 图文是从body里面取数据
const res = await service.auth.uploadNewsMaterial(data);
ctx.body = res;
}
service/auth.js
const Service = require("egg").Service;
const toArray = require("stream-to-array");
const WeChatAPI = require("co-wechat-api");
const fs = require("fs");
const path = require("path");
class AuthService extends Service {
constructor(ctx) {
super(ctx);
this.api = new WeChatAPI('appId', 'AppSecret');
}
// 上传永久素材-图文
async uploadNewsMaterial(news) {
// {
// "articles": [
// {
// "title": TITLE, // 标题
// "thumb_media_id": THUMB_MEDIA_ID, // 图文消息的封面图片素材id(必须是永久mediaID)
// "author": AUTHOR, // 作者
// "digest": DIGEST, // 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空。如果本字段为没有填写,则默认抓取正文前64个字。
// "show_cover_pic": SHOW_COVER_PIC(0 / 1), // 是否显示封面,0为false,即不显示,1为true,即显示
// "content": CONTENT, // 图文内容
// },
// //若新增的是多图文素材,则此处应还有几段articles结构
// ]
// }
const result = await this.api.uploadNewsMaterial(news);
return {
data: result,
msg: "图文永久素材上传成功",
};
}
}
module.exports = AuthService;
上传图文实例:
总结:图文上传成功后会返回:media_id
4.合并永久素材上传
reach max api daily quota limit rid: 600132aa-73568903-371806c9
那么需要请求一个接口去清除参看:
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/API_Call_Limits.html
POST HTTP调用: https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=ACCESS_TOKEN body传递appid
app/router.js
controller/auth.js
async uploadPermanentMaterial() {
const { ctx, service } = this;
// 为啥要在controller传入参数呢,因为在这里可以进行数据的校验。在service里面是不做数据校验的。
const params = ctx.request.query;
const body = ctx.request.body;
const res = await service.auth.uploadPermanentMaterial(params, body);
ctx.body = res;
}
service/auth.js
const Service = require("egg").Service;
const toArray = require("stream-to-array");
const WeChatAPI = require("co-wechat-api");
const fs = require("fs");
const path = require("path");
class AuthService extends Service {
constructor(ctx) {
super(ctx);
this.api = new WeChatAPI('appId', 'AppSecret');
}
async uploadPermanentMaterial(params, body) {
const { ctx } = this;
let result = null;
const writeMaterial = async () => {
if (params.type === "news") return;
const stream = await ctx.getFileStream();
const parts = await toArray(stream);
const buf = Buffer.concat(parts);
const fileName = stream.filename;
const filePath = path.resolve(__dirname, "../../media", fileName); // 文件存储的路径
fs.writeFile(filePath, buf, (err) => {
if (err) {
console.log(err);
}
});
return filePath;
};
const filePath = await writeMaterial();
switch (params.type) {
case "news":
result = await this.api.uploadNewsMaterial(body);
break;
case "video":
result = await this.api.uploadVideoMaterial(filePath, {
title: params.title,
introduction: params.introduction,
});
break;
case "image":
case "voice":
case "thumb":
result = await this.api.uploadMaterial(filePath, params.type);
break;
}
return {
data: result,
msg: params.type + "永久素材上传成功",
};
}
}
module.exports = AuthService;
前端如何传参:
视频:
query: type,title,introduction
body: formData的file
/api/v1/web/weChat/uploadPermanentMaterial?type=video&title=黄昏&introduction=看晚霞
图片/缩略图/语音:
query: type
body: formData的file
/api/v1/web/weChat/uploadPermanentMaterial?type=image/voice/thumb
图文:
query: type
body: json类型的数据
/api/v1/web/weChat/uploadPermanentMaterial?type=news
body:
{
"articles": [
{
"title": TITLE, // 标题
"thumb_media_id": THUMB_MEDIA_ID, // 图文消息的封面图片素材id(必须是永久mediaID)
"author": AUTHOR, // 作者
"digest": DIGEST, // 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空。如果本字段为没有填写,则默认抓取正文前64个字。
"show_cover_pic": SHOW_COVER_PIC(0 / 1), // 是否显示封面,0为false,即不显示,1为true,即显示
"content": CONTENT, // 图文内容
},
//若新增的是多图文素材,则此处应还有几段articles结构
]
}
5.更新图文素材
app/router.js
controller/auth.js
async updateNewsMaterial() {
const { ctx, service } = this;
const data = ctx.request.body;
const res = await service.auth.updateNewsMaterial(data);
ctx.body = res;
}
service/auth.js
const Service = require("egg").Service;
const toArray = require("stream-to-array");
const WeChatAPI = require("co-wechat-api");
const fs = require("fs");
const path = require("path");
class AuthService extends Service {
constructor(ctx) {
super(ctx);
this.api = new WeChatAPI('appId', 'AppSecret');
}
// 更新图文素材
async updateNewsMaterial(news) {
const result = await this.api.updateNewsMaterial(news);
return {
data: result,
msg: "图文永久素材修改成功",
};
}
}
module.exports = AuthService;
更新图文传参:
body传参
1.media_id // 要修改的图文消息的id
2.index // 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0
3.articles //修改的内容和新增一样
实例:
6.获取永久素材
app/router.js
controller/auth.js
async getMaterial() {
const { ctx, service } = this;
const data = ctx.request.query;
const res = await service.auth.getMaterial(data);
ctx.body = res;
}
service/auth.js
const Service = require("egg").Service;
const toArray = require("stream-to-array");
const WeChatAPI = require("co-wechat-api");
const fs = require("fs");
const path = require("path");
class AuthService extends Service {
constructor(ctx) {
super(ctx);
this.api = new WeChatAPI('appId', 'AppSecret');
}
// 获取永久素材
// type 和 mediaId
async getMaterial(params) {
let result = await this.api.getMaterial(params.mediaId);
let data = null;
switch (params.type) {
case "image":
case "voice":
case "thumb":
// 图片,语音,缩略图
const fileName = Date.now() + ".png"; // 文件名称 -正常情况是通过mediaId去数据库查询获取
const filePath = path.resolve(__dirname, "../../media", fileName); // 文件存储的路径
const base64 = result.toString("base64");
data = `data:image/png;base64,` + base64; // 这里的拼接的【image/png】也是需要通过mediaId去数据库查询获取mimeType字段
// 将文件下载到服务端-也可以不下载-直接返回给前端base64的图片
fs.writeFile(filePath, base64, (err) => {
if (err) {
console.log(err);
}
});
// 如果将文件上传到其他地方(七牛云)可以在这里操作
break;
default:
data = result; // news 和 video
}
return {
data,
msg: params.type + "永久素材获取成功",
};
}
}
module.exports = AuthService;
获取图片实例:
获取图文实例:
获取视频实例:
7.其他方法
removeMaterial 删除永久素材
getMaterialCount 获取素材总数
getMaterials 获取永久素材列表
uploadImage 上传图文消息内的图片获取URL
这四个方法我们这里就不实现了。直接调用即可。
文档传送门: https://doxmate.cool/node-webot/co-wechat-api/api.html#api_material_exports_removeMaterial
本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。
相关素材