Skip to main content

wx_sdk/mp/
media.rs

1//! Media Module (临时)素材文件接口相关
2use crate::SdkResult;
3use crate::{error::CommonResponse, wechat::WxApiRequestBuilder};
4use serde::{Deserialize, Serialize};
5
6use super::material::Articles;
7#[derive(Serialize, Deserialize)]
8pub struct MediaId {
9    pub media_id: String,
10}
11
12#[derive(Serialize, Deserialize, Debug)]
13pub struct UploadResponse {
14    #[serde(rename = "type")]
15    pub type_: String,
16    pub media_id: String,
17    pub created_at: i32,
18}
19
20/// A single "part" of a multipart/form-data body.
21///
22/// Yielded from the `FormData` stream.
23
24pub struct Part {
25    pub name: String,
26    pub filename: String,
27    pub content_type: String,
28    pub data: Vec<u8>,
29}
30
31#[derive(Serialize, Deserialize)]
32pub struct PicUrl {
33    pub url: String,
34}
35
36#[derive(Serialize, Deserialize, Debug)]
37pub struct MediaRes {
38    #[serde(rename = "type")]
39    pub type_: String,
40    #[serde(alias = "thumb_media_id")]
41    pub media_id: String,
42    pub created_at: i64,
43}
44/// Media Module (临时)素材文件接口相关
45pub struct MediaModule<'a, T: WxApiRequestBuilder>(pub(crate) &'a T);
46impl<'a, T: WxApiRequestBuilder> MediaModule<'a, T> {
47    /// 群发消息中的视频需要经过此接口再次上传得到 media_id 再群发
48    pub async fn uploadvideo<S: AsRef<str>>(
49        &self,
50        media_id: S,
51        title: Option<String>,
52        description: Option<String>,
53    ) -> SdkResult<UploadResponse> {
54        let base_url = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo";
55        let sdk = self.0;
56        let builder = sdk.wx_post(base_url).await?;
57        let res: CommonResponse<UploadResponse> = builder
58            .json(&serde_json::json!({
59                "media_id": media_id.as_ref().to_string(),
60                "title": title,
61                "description": description,
62            }))
63            .send()
64            .await?
65            .json()
66            .await?;
67
68        res.into()
69    }
70
71    /// 上传永久素材,上传图文消息内的图片
72    /// 本接口所上传的图片不占用公众号的素材库中图片数量的5000个的限制。图片仅支持jpg/png格式,大小必须在1MB以下。
73    pub async fn uploadimg(&self, form: Part) -> SdkResult<PicUrl> {
74        let base_url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg";
75        let sdk = self.0;
76        let part = reqwest::multipart::Part::bytes(form.data)
77            .file_name(form.filename)
78            .mime_str(form.content_type.as_ref());
79
80        let form = reqwest::multipart::Form::new().part(form.name, part.unwrap());
81        let builder = sdk.wx_post(base_url).await?;
82        let res: CommonResponse<PicUrl> = builder.multipart(form).send().await?.json().await?;
83
84        res.into()
85    }
86
87    /// 新增临时素材,媒体文件在微信后台保存时间为3天,即3天后media_id失效
88    pub async fn upload(&self, media_type: &str, media: &[i8]) -> SdkResult<MediaRes> {
89        let base_url = "https://api.weixin.qq.com/cgi-bin/media/upload";
90        let sdk = self.0;
91        let builder = sdk.wx_post(base_url).await?;
92        let builder = builder.query(&[("type", media_type)]);
93        let res: CommonResponse<MediaRes> = builder.form(media).send().await?.json().await?;
94        res.into()
95    }
96
97    ///公众号可以使用本接口获取临时素材(即下载临时的多媒体文件)。
98    ///本接口即为原“下载多媒体文件”接口。
99    pub async fn get<S: AsRef<str>>(&self, media_id: S) -> SdkResult<reqwest::Response> {
100        let base_url = "https://api.weixin.qq.com/cgi-bin/media/get";
101        let sdk = self.0;
102        let builder = sdk.wx_get(base_url).await?;
103        let builder = builder.query(&[("media_id", media_id.as_ref())]);
104        // 直接返回给前端处理了 https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_temporary_materials.html
105        Ok(builder.send().await?)
106    }
107
108    /// 上传图文消息素材【订阅号与服务号认证后均可用】效
109    pub async fn uploadnews(&self, articles: &[Articles]) -> SdkResult<MediaRes> {
110        let base_url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews";
111        let sdk = self.0;
112        let builder = sdk.wx_post(base_url).await?;
113        let res: CommonResponse<MediaRes> = builder
114            .json(&serde_json::json!({ "articles": articles }))
115            .send()
116            .await?
117            .json()
118            .await?;
119        res.into()
120    }
121}