Skip to main content

bpi_rs/creativecenter/
upload.rs

1// 创作中心上传 API
2//
3// [参考文档](https://github.com/Yuelioi/bilibili-API-collect/tree/cfc5fddcc8a94b74d91970bb5b4eaeb349addc47/docs/creativecenter/upload.md)
4
5use crate::BilibiliRequest;
6use crate::BpiError;
7use crate::BpiResult;
8use crate::creativecenter::CreativeCenterClient;
9use base64::{Engine as _, engine::general_purpose};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use std::fs;
13
14/// 上传封面返回结果
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct UploadCoverData {
18    pub url: String,
19}
20
21impl<'a> CreativeCenterClient<'a> {
22    /// 上传视频封面
23    ///
24    /// 上传视频封面图片,支持多种输入格式。
25    ///
26    /// # 参数
27    /// | 名称 | 类型 | 说明 |
28    /// | ---- | ---- | ---- |
29    /// | `mime_type` | &str | 图片 MIME 类型,如 image/jpeg |
30    /// | `cover` | `AsRef<str>` | 封面数据,可以是:纯 base64、完整 data URI、文件路径 |
31    ///
32    /// # 注意
33    /// 文件不得超过 20M
34    ///
35    /// # 文档
36    /// [上传视频封面](https://github.com/Yuelioi/bilibili-API-collect/tree/cfc5fddcc8a94b74d91970bb5b4eaeb349addc47/docs/creativecenter/upload.md#上传视频封面)
37    pub async fn upload_cover(
38        &self,
39        mime_type: &str,
40        cover: impl AsRef<str>,
41    ) -> BpiResult<UploadCoverData> {
42        let csrf = self.client.csrf()?;
43        let cover_str = cover.as_ref();
44
45        let final_cover = if cover_str.starts_with("data:") {
46            cover_str.to_string()
47        } else if cover_str
48            .chars()
49            .all(|c| (c.is_ascii_alphanumeric() || c == '+' || c == '/' || c == '='))
50        {
51            format!("data:{};base64,{}", mime_type, cover_str)
52        } else {
53            let file_bytes = fs::read(cover_str).map_err(|e| BpiError::Parse {
54                message: format!("读取文件失败: {}", e),
55            })?;
56            let file_base64 = general_purpose::STANDARD.encode(file_bytes);
57            format!("data:{};base64,{}", mime_type, file_base64)
58        };
59
60        let mut form = HashMap::new();
61        form.insert("csrf", csrf);
62        form.insert("cover", final_cover);
63
64        self.client
65            .post("https://member.bilibili.com/x/vu/web/cover/up")
66            .form(&form)
67            .send_bpi_payload("creativecenter.cover.upload")
68            .await
69    }
70}