Skip to main content

ncm_api_rs/api/
avatar_upload.rs

1use super::Query;
2use crate::error::Result;
3/// 上传头像
4/// 对应 Node.js module/avatar_upload.js + plugins/upload.js
5///
6/// 注意: 此端点需要调用者提供图片文件的二进制数据。
7/// 由于 Rust SDK 是纯库,文件读取由调用者负责。
8use crate::request::{ApiClient, ApiResponse, CryptoType};
9use serde_json::json;
10
11impl ApiClient {
12    /// 上传头像图片
13    ///
14    /// query 参数:
15    /// - `img_data`: 不通过 Query 传递,由专用参数传入
16    /// - `img_name`: 图片文件名
17    /// - `img_mimetype`: 图片 MIME 类型,默认 "image/jpeg"
18    ///
19    /// 此方法包含两步:
20    /// 1. 申请 NOS 上传 token
21    /// 2. 上传文件到 NOS
22    /// 3. 调用头像更新接口
23    pub async fn avatar_upload(&self, query: &Query, img_data: Vec<u8>) -> Result<ApiResponse> {
24        let img_name = query.get_or("img_name", "avatar.jpg");
25        let img_mimetype = query.get_or("img_mimetype", "image/jpeg");
26
27        // Step 1: 申请上传 token
28        let token_data = json!({
29            "bucket": "yyimgs",
30            "ext": "jpg",
31            "filename": img_name,
32            "local": false,
33            "nos_product": 0,
34            "return_body": "{\"code\":200,\"size\":\"$(ObjectSize)\"}",
35            "type": "other"
36        });
37
38        let token_res = self
39            .request(
40                "/api/nos/token/alloc",
41                token_data,
42                query.to_option(CryptoType::Weapi),
43            )
44            .await?;
45
46        let result = &token_res.body["result"];
47        let object_key = result["objectKey"].as_str().unwrap_or_default();
48        let token = result["token"].as_str().unwrap_or_default();
49        let doc_id = result["docId"].clone();
50
51        // Step 2: 上传文件到 NOS
52        let upload_url = format!(
53            "https://nosup-hz1.127.net/yyimgs/{}?offset=0&complete=true&version=1.0",
54            object_key
55        );
56
57        self.client
58            .post(&upload_url)
59            .header("x-nos-token", token)
60            .header("Content-Type", &img_mimetype)
61            .body(img_data)
62            .send()
63            .await
64            .map_err(crate::error::NcmError::Http)?;
65
66        // Step 3: 更新头像
67        let update_data = json!({
68            "imgid": doc_id
69        });
70
71        let update_res = self
72            .request(
73                "/api/user/avatar/upload/v1",
74                update_data,
75                query.to_option(CryptoType::default()),
76            )
77            .await?;
78
79        // 合并结果
80        let url_pre = format!("https://p1.music.126.net/{}", object_key);
81        let mut body = update_res.body.clone();
82        if let Some(obj) = body.as_object_mut() {
83            obj.insert("url_pre".to_string(), json!(url_pre));
84            obj.insert("imgId".to_string(), doc_id);
85        }
86
87        Ok(ApiResponse {
88            status: 200,
89            body,
90            cookie: update_res.cookie,
91        })
92    }
93}