use crate::common::api_endpoints::DriveApi;
use openlark_core::{
api::{ApiRequest, Response},
config::Config,
http::Transport,
SDKResult,
};
#[derive(Debug)]
pub struct DownloadFileRequest {
config: Config,
pub file_token: String,
pub range: Option<String>,
}
impl DownloadFileRequest {
pub fn new(config: Config, file_token: impl Into<String>) -> Self {
Self {
config,
file_token: file_token.into(),
range: None,
}
}
pub fn range(mut self, range: impl Into<String>) -> Self {
self.range = Some(range.into());
self
}
pub async fn execute(self) -> SDKResult<Response<Vec<u8>>> {
self.execute_with_options(openlark_core::req_option::RequestOption::default())
.await
}
pub async fn execute_with_options(
self,
option: openlark_core::req_option::RequestOption,
) -> SDKResult<Response<Vec<u8>>> {
if self.file_token.is_empty() {
return Err(openlark_core::error::validation_error(
"file_token",
"file_token 不能为空",
));
}
if let Some(r) = &self.range {
let r = r.trim();
if !r.starts_with("bytes=") {
return Err(openlark_core::error::validation_error(
"range",
"Range 必须以 bytes= 开头,例如 bytes=0-1023",
));
}
let range_spec = &r["bytes=".len()..];
let (start, end) = range_spec.split_once('-').ok_or_else(|| {
openlark_core::error::validation_error(
"range",
"Range 格式错误,应为 bytes=start-end,例如 bytes=0-1023",
)
})?;
if start.trim().is_empty() {
return Err(openlark_core::error::validation_error(
"range",
"Range start 不能为空,例如 bytes=0-1023",
));
}
if start.trim().parse::<u64>().is_err() {
return Err(openlark_core::error::validation_error(
"range",
"Range start 必须为非负整数",
));
}
if !end.trim().is_empty() && end.trim().parse::<u64>().is_err() {
return Err(openlark_core::error::validation_error(
"range",
"Range end 必须为非负整数或为空(例如 bytes=0-)",
));
}
}
let api_endpoint = DriveApi::DownloadFile(self.file_token.clone());
let mut request = ApiRequest::<Vec<u8>>::get(&api_endpoint.to_url());
if let Some(r) = &self.range {
request = request.header("Range", r);
}
Transport::request(request, &self.config, Some(option)).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_download_file_request_builder() {
let config = Config::builder()
.app_id("test_app_id")
.app_secret("test_app_secret")
.build();
let file_token = "test_file_token_123";
let range_header = "bytes=0-100";
let request = DownloadFileRequest::new(config.clone(), file_token).range(range_header);
assert_eq!(request.file_token, file_token);
assert_eq!(request.range, Some(range_header.to_string()));
}
#[test]
fn test_download_file_with_empty_file_token() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "");
assert_eq!(request.file_token, "");
}
#[test]
fn test_download_file_with_invalid_range_no_prefix() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "file_token").range("0-100");
assert_eq!(request.range, Some("0-100".to_string()));
}
#[test]
fn test_download_file_with_invalid_range_no_dash() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "file_token").range("bytes=0100");
assert_eq!(request.range, Some("bytes=0100".to_string()));
}
#[test]
fn test_download_file_with_invalid_range_empty_start() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "file_token").range("bytes=-100");
assert_eq!(request.range, Some("bytes=-100".to_string()));
}
#[test]
fn test_download_file_with_invalid_range_non_numeric() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "file_token").range("bytes=abc-100");
assert_eq!(request.range, Some("bytes=abc-100".to_string()));
}
#[test]
fn test_download_file_with_valid_range_end_empty() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "file_token").range("bytes=0-");
assert_eq!(request.range, Some("bytes=0-".to_string()));
}
#[test]
fn test_download_file_with_valid_range_full() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "file_token").range("bytes=0-1023");
assert_eq!(request.range, Some("bytes=0-1023".to_string()));
}
#[test]
fn test_download_file_without_range() {
let config = Config::default();
let request = DownloadFileRequest::new(config, "file_token");
assert_eq!(request.range, None);
}
}