素材管理
素材管理接口是公众号开发中用于管理图片、语音、视频、图文等多媒体内容的接口。微信公众平台提供了两种类型的素材管理方式:临时素材和永久素材。
素材类型与限制
微信公众号支持以下几种素材类型:
| 素材类型 | 大小限制 | 格式限制 | 其他限制 |
|---|---|---|---|
| 图片(image) | 2MB | JPG/PNG | - |
| 语音(voice) | 2MB | MP3/AMR/WAV | 播放长度不超过60s |
| 视频(video) | 10MB | MP4 | - |
| 缩略图(thumb) | 64KB | JPG | - |
| 图文(news) | - | - | 单图文消息:1条;多图文消息:8条 |
临时素材
临时素材是指在发送消息时上传的临时性质的多媒体文件,包括图片、语音、视频和缩略图。临时素材的有效期为3天。
上传临时素材
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE参数说明
| 参数 | 是否必须 | 说明 |
|---|---|---|
| access_token | 是 | 调用接口凭证 |
| type | 是 | 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) |
请求示例
使用form-data格式上传文件,media参数中包含文件内容。
POST https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=image HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="media"; filename="image.jpg"
Content-Type: image/jpeg
(二进制文件内容)
------WebKitFormBoundary7MA4YWxkTrZu0gW--返回结果
json
{
"type": "TYPE",
"media_id": "MEDIA_ID",
"created_at": 123456789
}返回参数说明
| 参数 | 说明 |
|---|---|
| type | 媒体文件类型 |
| media_id | 媒体文件ID,可用于发送消息 |
| created_at | 媒体文件上传时间戳 |
获取临时素材
接口说明
http
GET https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID参数说明
| 参数 | 是否必须 | 说明 |
|---|---|---|
| access_token | 是 | 调用接口凭证 |
| media_id | 是 | 媒体文件ID |
返回结果
如果请求成功,将直接返回文件内容,可以通过响应头中的Content-Type判断返回的文件类型。
对于视频文件,返回结果为JSON:
json
{
"video_url": "URL"
}永久素材
永久素材是指上传到微信服务器后长期存储的素材,包括图片、语音、视频和图文素材。每个公众号的永久素材数量有上限:图文消息素材、图片素材上限为5000,其他类型为1000。
上传永久图片素材
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=image参数说明
| 参数 | 是否必须 | 说明 |
|---|---|---|
| access_token | 是 | 调用接口凭证 |
| type | 是 | 媒体文件类型,此处固定为image |
请求示例
使用form-data格式上传文件,media参数中包含文件内容。
POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=image HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="media"; filename="image.jpg"
Content-Type: image/jpeg
(二进制文件内容)
------WebKitFormBoundary7MA4YWxkTrZu0gW--返回结果
json
{
"media_id": "MEDIA_ID",
"url": "URL"
}返回参数说明
| 参数 | 说明 |
|---|---|
| media_id | 新增的永久素材的media_id |
| url | 新增的图片素材的图片URL |
上传永久语音素材
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=voice参数说明
| 参数 | 是否必须 | 说明 |
|---|---|---|
| access_token | 是 | 调用接口凭证 |
| type | 是 | 媒体文件类型,此处固定为voice |
请求示例
使用form-data格式上传文件,media参数中包含文件内容。
返回结果
json
{
"media_id": "MEDIA_ID"
}上传永久视频素材
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=video参数说明
| 参数 | 是否必须 | 说明 |
|---|---|---|
| access_token | 是 | 调用接口凭证 |
| type | 是 | 媒体文件类型,此处固定为video |
请求示例
使用form-data格式上传文件,media参数中包含文件内容,description参数包含视频描述信息的JSON字符串。
POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=video HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="media"; filename="video.mp4"
Content-Type: video/mp4
(二进制文件内容)
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="description"
{
"title": "视频标题",
"introduction": "视频描述"
}
------WebKitFormBoundary7MA4YWxkTrZu0gW--返回结果
json
{
"media_id": "MEDIA_ID"
}上传永久图文素材
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN请求参数
json
{
"articles": [
{
"title": "标题1",
"thumb_media_id": "THUMB_MEDIA_ID",
"author": "作者",
"digest": "摘要",
"show_cover_pic": 1,
"content": "正文内容,支持HTML标签",
"content_source_url": "原文链接"
},
{
"title": "标题2",
"thumb_media_id": "THUMB_MEDIA_ID",
"author": "作者",
"digest": "摘要",
"show_cover_pic": 0,
"content": "正文内容,支持HTML标签",
"content_source_url": "原文链接"
}
]
}参数说明
| 参数 | 是否必须 | 说明 |
|---|---|---|
| title | 是 | 标题 |
| thumb_media_id | 是 | 图文消息的封面图片素材id(必须是永久mediaID) |
| author | 否 | 作者 |
| digest | 否 | 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空 |
| show_cover_pic | 是 | 是否显示封面,0为不显示,1为显示 |
| content | 是 | 图文消息的具体内容,支持HTML标签,必须少于2万字符 |
| content_source_url | 否 | 图文消息的原文地址,即点击"阅读原文"后的URL |
返回结果
json
{
"media_id": "MEDIA_ID"
}获取永久素材
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=ACCESS_TOKEN请求参数
json
{
"media_id": "MEDIA_ID"
}返回结果(图文素材)
json
{
"news_item": [
{
"title": "标题1",
"author": "作者",
"digest": "摘要",
"content": "正文内容",
"content_source_url": "原文链接",
"thumb_media_id": "THUMB_MEDIA_ID",
"show_cover_pic": 1,
"url": "文章URL",
"thumb_url": "封面图片URL"
},
{
"title": "标题2",
"author": "作者",
"digest": "摘要",
"content": "正文内容",
"content_source_url": "原文链接",
"thumb_media_id": "THUMB_MEDIA_ID",
"show_cover_pic": 0,
"url": "文章URL",
"thumb_url": "封面图片URL"
}
]
}删除永久素材
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN请求参数
json
{
"media_id": "MEDIA_ID"
}返回结果
json
{
"errcode": 0,
"errmsg": "ok"
}获取素材总数
接口说明
http
GET https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN返回结果
json
{
"voice_count": 语音总数,
"video_count": 视频总数,
"image_count": 图片总数,
"news_count": 图文总数
}获取素材列表
接口说明
http
POST https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN请求参数
json
{
"type": "news",
"offset": 0,
"count": 20
}| 参数 | 是否必须 | 说明 |
|---|---|---|
| type | 是 | 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news) |
| offset | 是 | 从全部素材的该偏移位置开始返回,0表示从第一个素材返回 |
| count | 是 | 返回素材的数量,取值在1到20之间 |
返回结果(图文素材)
json
{
"total_count": 总素材数,
"item_count": 本次调用获取的素材数,
"item": [
{
"media_id": "MEDIA_ID",
"content": {
"news_item": [
{
"title": "标题1",
"author": "作者",
"digest": "摘要",
"content": "正文内容",
"content_source_url": "原文链接",
"thumb_media_id": "THUMB_MEDIA_ID",
"show_cover_pic": 1,
"url": "文章URL",
"thumb_url": "封面图片URL"
}
]
},
"update_time": 更新时间
}
]
}示例代码
上传临时素材(Node.js)
javascript
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
async function uploadTemporaryMedia(accessToken, type, filePath) {
try {
const form = new FormData();
form.append('media', fs.createReadStream(filePath));
const url = `https://api.weixin.qq.com/cgi-bin/media/upload?access_token=${accessToken}&type=${type}`;
const response = await axios.post(url, form, {
headers: form.getHeaders()
});
console.log('上传临时素材成功:', response.data);
return response.data;
} catch (error) {
console.error('上传临时素材失败:', error);
throw error;
}
}
// 使用示例
const accessToken = 'your_access_token';
uploadTemporaryMedia(accessToken, 'image', './image.jpg');上传永久图文素材(PHP)
php
<?php
function uploadPermanentNews($accessToken, $articles) {
$url = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token={$accessToken}";
$data = [
'articles' => $articles
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result, true);
}
// 使用示例
$accessToken = 'your_access_token';
$articles = [
[
'title' => '微信公众号开发指南',
'thumb_media_id' => 'thumb_media_id',
'author' => '开发者',
'digest' => '本文介绍微信公众号开发的基本流程和接口使用',
'show_cover_pic' => 1,
'content' => '<p>这是正文内容</p>',
'content_source_url' => 'https://example.com/article'
]
];
$result = uploadPermanentNews($accessToken, $articles);
print_r($result);
?>注意事项
- 临时素材的media_id是可复用的,但有效期为3天
- 永久素材的数量有限制,图文消息素材、图片素材上限为5000,其他类型为1000
- 素材的格式、大小、时长等都有严格限制,请参考官方文档
- 图文消息的正文中,外链图片必须使用微信素材管理接口上传图片获取URL
- 永久素材的media_id不会过期,可长期使用
- 上传图文消息内的图片获取URL,请使用专门的接口:https://api.weixin.qq.com/cgi-bin/media/uploadimg
