use super::KalamLinkClient;
use crate::{
error::{KalamLinkError, Result},
models::{BoundFileRef, FileDownload, FileRef},
};
impl KalamLinkClient {
pub async fn download_file(
&self,
file_ref: &FileRef,
namespace: &str,
table: &str,
target_user_id: Option<&str>,
) -> Result<FileDownload> {
let mut url = file_ref.download_url(self.base_url(), namespace, table);
if let Some(user_id) = target_user_id {
url.push_str("?user_id=");
url.push_str(user_id);
}
let auth = self.jwt_for_http_request().await?;
let request = self.http_client().get(&url);
let request = auth.apply_to_request(request)?;
let response = request.send().await.map_err(|error| {
KalamLinkError::NetworkError(format!("file download request failed: {error}"))
})?;
let status = response.status();
if !status.is_success() {
let message = response.text().await.unwrap_or_default();
return Err(KalamLinkError::ServerError {
status_code: status.as_u16(),
message: if message.is_empty() {
format!("file download failed with status {status}")
} else {
message
},
});
}
let content_type = response
.headers()
.get(reqwest::header::CONTENT_TYPE)
.and_then(|value| value.to_str().ok())
.map(str::to_string);
let content_disposition = response
.headers()
.get(reqwest::header::CONTENT_DISPOSITION)
.and_then(|value| value.to_str().ok())
.map(str::to_string);
let bytes = response.bytes().await.map_err(|error| {
KalamLinkError::NetworkError(format!("failed to read file download body: {error}"))
})?;
Ok(FileDownload {
bytes: bytes.to_vec(),
content_type,
content_disposition,
})
}
pub async fn download_bound_file(
&self,
file_ref: &BoundFileRef,
target_user_id: Option<&str>,
) -> Result<FileDownload> {
self.download_file(
file_ref.file_ref(),
file_ref.namespace(),
file_ref.table(),
target_user_id,
)
.await
}
}