bpi_rs/creativecenter/
upload.rs1use std::collections::HashMap;
6
7use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
8
9use base64::{ Engine as _, engine::general_purpose };
10use serde::{ Deserialize, Serialize };
11use std::fs;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct UploadCoverData {
16 pub url: String,
17}
18
19impl BpiClient {
20 pub async fn upload_cover(
36 &self,
37 mime_type: &str,
38 cover: impl AsRef<str>
39 ) -> Result<BpiResponse<UploadCoverData>, BpiError> {
40 let csrf = self.csrf()?;
41 let cover_str = cover.as_ref();
42
43 let final_cover = if cover_str.starts_with("data:") {
44 cover_str.to_string()
45 } else if
46 cover_str
47 .chars()
48 .all(|c| (c.is_ascii_alphanumeric() || c == '+' || c == '/' || c == '='))
49 {
50 format!("data:{};base64,{}", mime_type, cover_str)
51 } else {
52 let file_bytes = fs::read(cover_str).map_err(|e| BpiError::Parse {
53 message: format!("读取文件失败: {}", e),
54 })?;
55 let file_base64 = general_purpose::STANDARD.encode(file_bytes);
56 format!("data:{};base64,{}", mime_type, file_base64)
57 };
58
59 let mut form = HashMap::new();
60 form.insert("csrf", csrf);
61 form.insert("cover", final_cover);
62
63 self
64 .post("https://member.bilibili.com/x/vu/web/cover/up")
65 .form(&form)
66 .send_bpi("上传视频封面").await
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 #[allow(unused_imports)]
74 use base64::{ Engine as _, engine::general_purpose };
75 use std::fs;
76
77 async fn run_upload_test(
78 bpi: &BpiClient,
79 mime_type: &str,
80 cover: &str
81 ) -> Result<(), Box<BpiError>> {
82 let data = bpi.upload_cover(mime_type, cover).await?.into_data()?;
83 tracing::info!("上传成功,封面地址: {}", data.url);
84 Ok(())
85 }
86
87 #[tokio::test]
88 async fn test_cover_upload() -> Result<(), Box<BpiError>> {
89 let bpi = BpiClient::new();
90
91 let img_data = fs::read("./assets/test.jpg").map_err(|_| BpiError::parse("读取图片失败"))?;
101 let img_base64 = general_purpose::STANDARD.encode(&img_data);
102 let img_data_uri = format!("data:image/jpeg;base64,{}", img_base64);
103 run_upload_test(&bpi, "image/jpeg", &img_data_uri).await?;
104
105 Ok(())
106 }
107}