微信订阅号-永久素材上传和获取

发布于 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=newsbody:{  "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 // 要修改的图文消息的id2.index // 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为03.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 我们将第一时间删除。

相关素材