Skip to main content

zai_rs/file/
content.rs

1use std::sync::Arc;
2
3use crate::client::{
4    endpoints::{ApiBase, EndpointConfig, join_url, paths},
5    http::{HttpClient, HttpClientConfig},
6};
7
8/// File content request (GET /paas/v4/files/{file_id}/content)
9pub struct FileContentRequest {
10    pub key: String,
11    url: String,
12    endpoint_config: EndpointConfig,
13    api_base: ApiBase,
14    file_id: String,
15    http_config: Arc<HttpClientConfig>,
16    _body: (),
17}
18
19impl FileContentRequest {
20    pub fn new(key: String, file_id: impl Into<String>) -> Self {
21        let file_id = file_id.into();
22        let endpoint_config = EndpointConfig::default();
23        let api_base = ApiBase::PaasV4;
24        let url = endpoint_config.url(
25            &api_base,
26            &join_url(&join_url(paths::FILES, &file_id), "content"),
27        );
28        Self {
29            key,
30            url,
31            endpoint_config,
32            api_base,
33            file_id,
34            http_config: Arc::new(HttpClientConfig::default()),
35            _body: (),
36        }
37    }
38
39    fn rebuild_url(&mut self) {
40        self.url = self.endpoint_config.url(
41            &self.api_base,
42            &join_url(&join_url(paths::FILES, &self.file_id), "content"),
43        );
44    }
45
46    pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
47        self.api_base = ApiBase::Custom(base_url.into());
48        self.rebuild_url();
49        self
50    }
51
52    pub fn with_endpoint_config(mut self, endpoint_config: EndpointConfig) -> Self {
53        self.endpoint_config = endpoint_config;
54        self.rebuild_url();
55        self
56    }
57
58    pub fn with_http_config(mut self, config: HttpClientConfig) -> Self {
59        self.http_config = Arc::new(config);
60        self
61    }
62
63    /// Send the request and return raw bytes of the file content.
64    pub async fn send(&self) -> crate::ZaiResult<Vec<u8>> {
65        let resp: reqwest::Response = self.get().await?;
66
67        let status = resp.status();
68
69        if !status.is_success() {
70            let text = resp.text().await.unwrap_or_default();
71
72            return Err(crate::client::error::ZaiError::from_api_response(
73                status.as_u16(),
74                0,
75                text,
76            ));
77        }
78
79        let bytes = resp.bytes().await?;
80        Ok(bytes.to_vec())
81    }
82
83    /// It will create parent directories if missing.
84    /// Returns the number of bytes written.
85    pub async fn send_to<P: AsRef<std::path::Path>>(&self, path: P) -> crate::ZaiResult<usize> {
86        let bytes = self.send().await?;
87
88        let p = path.as_ref();
89
90        if let Some(parent) = p.parent()
91            && !parent.as_os_str().is_empty()
92        {
93            std::fs::create_dir_all(parent)?;
94        }
95        use std::io::Write;
96        let mut f = std::fs::File::create(p)?;
97        f.write_all(&bytes)?;
98        Ok(bytes.len())
99    }
100}
101
102impl HttpClient for FileContentRequest {
103    type Body = ();
104    type ApiUrl = String;
105    type ApiKey = String;
106
107    fn api_url(&self) -> &Self::ApiUrl {
108        &self.url
109    }
110    fn api_key(&self) -> &Self::ApiKey {
111        &self.key
112    }
113    fn body(&self) -> &Self::Body {
114        &self._body
115    }
116
117    fn http_config(&self) -> Arc<HttpClientConfig> {
118        self.http_config.clone()
119    }
120}