Skip to main content

zai_rs/file/
content.rs

1use crate::client::ZaiClient;
2
3/// Buffered bytes returned by the file-content operation.
4pub type ByteStream = Vec<u8>;
5
6/// File content request (GET /paas/v4/files/{file_id}/content)
7pub struct FileContentRequest {
8    file_id: String,
9}
10
11impl FileContentRequest {
12    /// Create a new content request for the given file id.
13    pub fn new(file_id: impl Into<String>) -> Self {
14        Self {
15            file_id: file_id.into(),
16        }
17    }
18
19    /// Send the request via a [`ZaiClient`] and return raw bytes of the file
20    /// content.
21    pub async fn send_via(&self, client: &ZaiClient) -> crate::ZaiResult<ByteStream> {
22        Ok(self.fetch_bytes_via(client).await?.to_vec())
23    }
24
25    async fn fetch_bytes_via(&self, client: &ZaiClient) -> crate::ZaiResult<bytes::Bytes> {
26        crate::client::validation::require_non_blank(&self.file_id, "file_id")?;
27        let route = crate::client::routes::FILES_GET_CONTENT;
28        let url = client.endpoints().resolve_route(route, &[&self.file_id])?;
29        client.send_empty_bytes(route.method(), url).await
30    }
31
32    /// Send via a [`ZaiClient`] and write the file content to `path`.
33    ///
34    /// Parent directories are created when missing. The response is buffered,
35    /// written to a private same-directory temporary file, synced, and then
36    /// published atomically. An existing destination is never replaced.
37    /// Returns the number of bytes written.
38    pub async fn send_to_via<P: AsRef<std::path::Path>>(
39        &self,
40        client: &ZaiClient,
41        path: P,
42    ) -> crate::ZaiResult<usize> {
43        let bytes = self.fetch_bytes_via(client).await?;
44
45        let p = path.as_ref();
46
47        // Use `tokio::fs` so a slow/networked filesystem or a large file can't
48        // stall the async runtime worker (mirrors the upload-path fix).
49        if let Some(parent) = p.parent()
50            && !parent.as_os_str().is_empty()
51        {
52            tokio::fs::create_dir_all(parent).await?;
53        }
54        let length = bytes.len();
55        crate::client::transport::download::atomic_download(p, bytes).await?;
56        Ok(length)
57    }
58}