open_lark/service/cloud_docs/drive/v1/
file.rs

1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5    core::{
6        api_req::ApiRequest,
7        api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
8        config::Config,
9        constants::AccessTokenType,
10        http::Transport,
11        req_option::RequestOption,
12        SDKResult,
13    },
14    impl_executable_builder_owned,
15};
16
17/// 文件服务 - 处理除上传下载外的其他文件操作
18pub struct FileService {
19    config: Config,
20}
21
22impl FileService {
23    pub fn new(config: Config) -> Self {
24        Self { config }
25    }
26
27    /// 获取文件元数据
28    ///
29    /// 该接口用于根据文件token获取文件的元数据信息。
30    ///
31    /// <https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/drive-v1/meta/batch_query>
32    pub async fn get_file_meta(
33        &self,
34        request: GetFileMetaRequest,
35        option: Option<RequestOption>,
36    ) -> SDKResult<BaseResponse<GetFileMetaRespData>> {
37        let api_req = ApiRequest {
38            http_method: Method::POST,
39            api_path: "/open-apis/drive/v1/metas/batch_query".to_string(),
40            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
41            body: serde_json::to_vec(&request)?,
42            ..Default::default()
43        };
44
45        let api_resp = Transport::request(api_req, &self.config, option).await?;
46        Ok(api_resp)
47    }
48
49    /// 获取文件统计信息
50    ///
51    /// 该接口用于根据文件token获取文件的统计信息,如浏览次数等。
52    ///
53    /// <https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/drive-v1/file-statistics/get>
54    pub async fn get_file_statistics(
55        &self,
56        request: GetFileStatisticsRequest,
57        option: Option<RequestOption>,
58    ) -> SDKResult<BaseResponse<GetFileStatisticsRespData>> {
59        let api_req = ApiRequest {
60            http_method: Method::GET,
61            api_path: format!(
62                "/open-apis/drive/v1/files/{}/statistics",
63                request.file_token
64            ),
65            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
66            ..Default::default()
67        };
68
69        let api_resp = Transport::request(api_req, &self.config, option).await?;
70        Ok(api_resp)
71    }
72
73    /// 获取文件访问记录
74    ///
75    /// 该接口用于获取文件的访问记录列表。
76    ///
77    /// <https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/drive-v1/file-view_record/list>
78    pub async fn list_file_view_records(
79        &self,
80        request: ListFileViewRecordsRequest,
81        option: Option<RequestOption>,
82    ) -> SDKResult<BaseResponse<ListFileViewRecordsRespData>> {
83        let mut api_req = ApiRequest {
84            http_method: Method::GET,
85            api_path: format!(
86                "/open-apis/drive/v1/files/{}/view_records",
87                request.file_token
88            ),
89            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
90            ..Default::default()
91        };
92
93        // 添加查询参数
94        if let Some(page_token) = request.page_token {
95            api_req
96                .query_params
97                .insert("page_token".to_string(), page_token);
98        }
99        if let Some(page_size) = request.page_size {
100            api_req
101                .query_params
102                .insert("page_size".to_string(), page_size.to_string());
103        }
104
105        let api_resp = Transport::request(api_req, &self.config, option).await?;
106        Ok(api_resp)
107    }
108
109    /// 新建文件
110    ///
111    /// 该接口用于在指定文件夹中新建文件。
112    ///
113    /// <https://open.feishu.cn/document/ukTMukTMukTM/uQTNzUjL0UzM14CN1MTN>
114    pub async fn create_file(
115        &self,
116        request: CreateFileRequest,
117        option: Option<RequestOption>,
118    ) -> SDKResult<BaseResponse<CreateFileRespData>> {
119        let api_req = ApiRequest {
120            http_method: Method::POST,
121            api_path: "/open-apis/drive/v1/files".to_string(),
122            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
123            body: serde_json::to_vec(&request)?,
124            ..Default::default()
125        };
126
127        let api_resp = Transport::request(api_req, &self.config, option).await?;
128        Ok(api_resp)
129    }
130
131    /// 复制文件
132    ///
133    /// 该接口用于复制文件到指定文件夹。
134    ///
135    /// <https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/drive-v1/file/copy>
136    pub async fn copy_file(
137        &self,
138        request: CopyFileRequest,
139        option: Option<RequestOption>,
140    ) -> SDKResult<BaseResponse<CopyFileRespData>> {
141        // 构建请求体
142        let body = serde_json::json!({
143            "name": request.name,
144            "type": request.copy_type,
145            "parent_token": request.parent_token
146        });
147
148        let api_req = ApiRequest {
149            http_method: Method::POST,
150            api_path: format!("/open-apis/drive/v1/files/{}/copy", request.file_token),
151            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
152            body: serde_json::to_vec(&body)?,
153            ..Default::default()
154        };
155
156        let api_resp = Transport::request(api_req, &self.config, option).await?;
157        Ok(api_resp)
158    }
159
160    /// 删除文件
161    ///
162    /// 该接口用于删除文件。
163    ///
164    /// <https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/drive-v1/file/delete>
165    pub async fn delete_file(
166        &self,
167        request: DeleteFileRequest,
168        option: Option<RequestOption>,
169    ) -> SDKResult<BaseResponse<DeleteFileRespData>> {
170        let api_req = ApiRequest {
171            http_method: Method::DELETE,
172            api_path: format!("/open-apis/drive/v1/files/{}", request.file_token),
173            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
174            ..Default::default()
175        };
176
177        let api_resp = Transport::request(api_req, &self.config, option).await?;
178        Ok(api_resp)
179    }
180
181    /// 创建文件快捷方式
182    ///
183    /// 该接口用于创建文件的快捷方式。
184    ///
185    /// <https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/drive-v1/file/create_shortcut>
186    pub async fn create_file_shortcut(
187        &self,
188        request: CreateFileShortcutRequest,
189        option: Option<RequestOption>,
190    ) -> SDKResult<BaseResponse<CreateFileShortcutRespData>> {
191        let api_req = ApiRequest {
192            http_method: Method::POST,
193            api_path: "/open-apis/drive/v1/files/create_shortcut".to_string(),
194            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
195            body: serde_json::to_vec(&request)?,
196            ..Default::default()
197        };
198
199        let api_resp = Transport::request(api_req, &self.config, option).await?;
200        Ok(api_resp)
201    }
202
203    /// 搜索文件
204    ///
205    /// 该接口用于搜索文件。
206    ///
207    /// <https://open.feishu.cn/document/ukTMukTMukTM/ugDM4UjL4ADO14COwgTN>
208    pub async fn search_files(
209        &self,
210        request: SearchFilesRequest,
211        option: Option<RequestOption>,
212    ) -> SDKResult<BaseResponse<SearchFilesRespData>> {
213        let mut api_req = ApiRequest {
214            http_method: Method::GET,
215            api_path: "/open-apis/drive/v1/files/search".to_string(),
216            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
217            ..Default::default()
218        };
219
220        // 添加查询参数
221        api_req
222            .query_params
223            .insert("search_key".to_string(), request.search_key);
224        if let Some(count) = request.count {
225            api_req
226                .query_params
227                .insert("count".to_string(), count.to_string());
228        }
229        if let Some(offset) = request.offset {
230            api_req
231                .query_params
232                .insert("offset".to_string(), offset.to_string());
233        }
234        if let Some(owner_ids) = request.owner_ids {
235            api_req
236                .query_params
237                .insert("owner_ids".to_string(), owner_ids.join(","));
238        }
239
240        let api_resp = Transport::request(api_req, &self.config, option).await?;
241        Ok(api_resp)
242    }
243
244    /// 分片上传文件-预上传
245    ///
246    /// 该接口用于分片上传的预上传步骤,获取上传事务ID和分片信息。
247    ///
248    /// <https://open.feishu.cn/document/server-docs/docs/drive-v1/upload/multipart-upload-file-/upload_prepare>
249    pub async fn upload_prepare(
250        &self,
251        request: FileUploadPrepareRequest,
252        option: Option<RequestOption>,
253    ) -> SDKResult<BaseResponse<FileUploadPrepareRespData>> {
254        let api_req = ApiRequest {
255            http_method: Method::POST,
256            api_path: "/open-apis/drive/v1/files/upload_prepare".to_string(),
257            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
258            body: serde_json::to_vec(&request)?,
259            ..Default::default()
260        };
261
262        let api_resp = Transport::request(api_req, &self.config, option).await?;
263        Ok(api_resp)
264    }
265
266    /// 分片上传文件-上传分片
267    ///
268    /// 该接口用于上传文件分片。
269    ///
270    /// <https://open.feishu.cn/document/server-docs/docs/drive-v1/upload/multipart-upload-file-/upload_part>
271    pub async fn upload_part(
272        &self,
273        request: FileUploadPartRequest,
274        option: Option<RequestOption>,
275    ) -> SDKResult<BaseResponse<FileUploadPartRespData>> {
276        let mut api_req = request.api_req;
277        api_req.http_method = Method::POST;
278        api_req.api_path = "/open-apis/drive/v1/files/upload_part".to_string();
279        api_req.supported_access_token_types = vec![AccessTokenType::User, AccessTokenType::Tenant];
280
281        let api_resp = Transport::request(api_req, &self.config, option).await?;
282        Ok(api_resp)
283    }
284
285    /// 分片上传文件-完成上传
286    ///
287    /// 该接口用于完成分片上传。
288    ///
289    /// <https://open.feishu.cn/document/server-docs/docs/drive-v1/upload/multipart-upload-file-/upload_finish>
290    pub async fn upload_finish(
291        &self,
292        request: FileUploadFinishRequest,
293        option: Option<RequestOption>,
294    ) -> SDKResult<BaseResponse<FileUploadFinishRespData>> {
295        let api_req = ApiRequest {
296            http_method: Method::POST,
297            api_path: "/open-apis/drive/v1/files/upload_finish".to_string(),
298            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
299            body: serde_json::to_vec(&request)?,
300            ..Default::default()
301        };
302
303        let api_resp = Transport::request(api_req, &self.config, option).await?;
304        Ok(api_resp)
305    }
306
307    /// 创建导入任务
308    ///
309    /// 该接口用于创建文档导入任务。
310    ///
311    /// <https://open.feishu.cn/document/server-docs/docs/drive-v1/import_task/create>
312    pub async fn create_import_task(
313        &self,
314        request: CreateImportTaskRequest,
315        option: Option<RequestOption>,
316    ) -> SDKResult<BaseResponse<CreateImportTaskRespData>> {
317        let api_req = ApiRequest {
318            http_method: Method::POST,
319            api_path: "/open-apis/drive/v1/import_tasks".to_string(),
320            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
321            body: serde_json::to_vec(&request)?,
322            ..Default::default()
323        };
324
325        let api_resp = Transport::request(api_req, &self.config, option).await?;
326        Ok(api_resp)
327    }
328
329    /// 查询导入任务结果
330    ///
331    /// 该接口用于查询导入任务的执行结果。
332    ///
333    /// <https://open.feishu.cn/document/server-docs/docs/drive-v1/import_task/get>
334    pub async fn get_import_task(
335        &self,
336        request: GetImportTaskRequest,
337        option: Option<RequestOption>,
338    ) -> SDKResult<BaseResponse<GetImportTaskRespData>> {
339        let api_req = ApiRequest {
340            http_method: Method::GET,
341            api_path: format!("/open-apis/drive/v1/import_tasks/{}", request.ticket),
342            supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
343            ..Default::default()
344        };
345
346        let api_resp = Transport::request(api_req, &self.config, option).await?;
347        Ok(api_resp)
348    }
349}
350
351// === 请求和响应数据结构 ===
352
353/// 获取文件元数据请求参数
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct GetFileMetaRequest {
356    /// 文件token列表
357    pub request_docs: Vec<RequestDoc>,
358    /// 是否获取额外信息
359    pub with_url: Option<bool>,
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize)]
363pub struct RequestDoc {
364    /// 文件token
365    pub doc_token: String,
366    /// 文件类型
367    pub doc_type: String,
368}
369
370impl GetFileMetaRequest {
371    pub fn new(docs: Vec<(String, String)>) -> Self {
372        Self {
373            request_docs: docs
374                .into_iter()
375                .map(|(token, doc_type)| RequestDoc {
376                    doc_token: token,
377                    doc_type,
378                })
379                .collect(),
380            with_url: Some(true),
381        }
382    }
383}
384
385/// 获取文件元数据响应数据
386#[derive(Debug, Clone, Serialize, Deserialize)]
387pub struct GetFileMetaRespData {
388    /// 文件元数据列表
389    pub metas: Vec<FileMeta>,
390}
391
392#[derive(Debug, Clone, Serialize, Deserialize)]
393pub struct FileMeta {
394    /// 文件token
395    pub doc_token: String,
396    /// 文件类型
397    pub doc_type: String,
398    /// 文件标题
399    pub title: String,
400    /// 拥有者ID
401    pub owner_id: String,
402    /// 创建时间
403    pub create_time: String,
404    /// 更新时间
405    pub update_time: String,
406    /// 文件URL
407    pub url: Option<String>,
408}
409
410impl ApiResponseTrait for GetFileMetaRespData {
411    fn data_format() -> ResponseFormat {
412        ResponseFormat::Data
413    }
414}
415
416/// 获取文件统计信息请求参数
417#[derive(Debug, Clone, Serialize, Deserialize)]
418pub struct GetFileStatisticsRequest {
419    /// 文件token
420    pub file_token: String,
421}
422
423impl GetFileStatisticsRequest {
424    pub fn new(file_token: impl Into<String>) -> Self {
425        Self {
426            file_token: file_token.into(),
427        }
428    }
429}
430
431/// 获取文件统计信息响应数据
432#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct GetFileStatisticsRespData {
434    /// 文件浏览次数
435    pub uv: i64,
436    /// 文件浏览人数
437    pub pv: i64,
438    /// 文件点赞数
439    pub like_count: i64,
440    /// 文件评论数
441    pub comment_count: i64,
442}
443
444impl ApiResponseTrait for GetFileStatisticsRespData {
445    fn data_format() -> ResponseFormat {
446        ResponseFormat::Data
447    }
448}
449
450/// 获取文件访问记录请求参数
451#[derive(Debug, Clone, Serialize, Deserialize)]
452pub struct ListFileViewRecordsRequest {
453    /// 文件token
454    pub file_token: String,
455    /// 分页token
456    pub page_token: Option<String>,
457    /// 分页大小
458    pub page_size: Option<i32>,
459}
460
461impl ListFileViewRecordsRequest {
462    pub fn new(file_token: impl Into<String>) -> Self {
463        Self {
464            file_token: file_token.into(),
465            page_token: None,
466            page_size: None,
467        }
468    }
469
470    pub fn with_page_token(mut self, page_token: impl Into<String>) -> Self {
471        self.page_token = Some(page_token.into());
472        self
473    }
474
475    pub fn with_page_size(mut self, page_size: i32) -> Self {
476        self.page_size = Some(page_size);
477        self
478    }
479}
480
481/// 获取文件访问记录响应数据
482#[derive(Debug, Clone, Serialize, Deserialize)]
483pub struct ListFileViewRecordsRespData {
484    /// 是否还有更多数据
485    pub has_more: bool,
486    /// 下一页token
487    pub page_token: Option<String>,
488    /// 访问记录列表
489    pub items: Vec<FileViewRecord>,
490}
491
492#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct FileViewRecord {
494    /// 访问者ID
495    pub viewer_id: String,
496    /// 访问者名称
497    pub viewer_name: String,
498    /// 访问时间
499    pub view_time: String,
500    /// 访问设备
501    pub view_device: String,
502}
503
504impl ApiResponseTrait for ListFileViewRecordsRespData {
505    fn data_format() -> ResponseFormat {
506        ResponseFormat::Data
507    }
508}
509
510/// 新建文件请求参数
511#[derive(Debug, Clone, Serialize, Deserialize)]
512pub struct CreateFileRequest {
513    /// 文件名称
514    pub title: String,
515    /// 文件类型
516    #[serde(rename = "type")]
517    pub file_type: String,
518    /// 父文件夹token
519    pub parent_token: String,
520}
521
522impl CreateFileRequest {
523    pub fn new(
524        title: impl Into<String>,
525        file_type: impl Into<String>,
526        parent_token: impl Into<String>,
527    ) -> Self {
528        Self {
529            title: title.into(),
530            file_type: file_type.into(),
531            parent_token: parent_token.into(),
532        }
533    }
534}
535
536/// 新建文件响应数据
537#[derive(Debug, Clone, Serialize, Deserialize)]
538pub struct CreateFileRespData {
539    /// 新建文件的token
540    pub token: String,
541    /// 新建文件的链接
542    pub url: String,
543}
544
545impl ApiResponseTrait for CreateFileRespData {
546    fn data_format() -> ResponseFormat {
547        ResponseFormat::Data
548    }
549}
550
551/// 复制文件请求参数
552#[derive(Debug, Clone, Serialize, Deserialize)]
553pub struct CopyFileRequest {
554    /// 文件token
555    pub file_token: String,
556    /// 新文件名称
557    pub name: String,
558    /// 复制类型
559    #[serde(rename = "type")]
560    pub copy_type: String,
561    /// 目标父文件夹token
562    pub parent_token: String,
563}
564
565impl CopyFileRequest {
566    pub fn new(
567        file_token: impl Into<String>,
568        name: impl Into<String>,
569        parent_token: impl Into<String>,
570    ) -> Self {
571        Self {
572            file_token: file_token.into(),
573            name: name.into(),
574            copy_type: "copy".to_string(),
575            parent_token: parent_token.into(),
576        }
577    }
578}
579
580/// 复制文件响应数据
581#[derive(Debug, Clone, Serialize, Deserialize)]
582pub struct CopyFileRespData {
583    /// 复制后文件的token
584    pub token: String,
585    /// 复制后文件的链接
586    pub url: String,
587}
588
589impl ApiResponseTrait for CopyFileRespData {
590    fn data_format() -> ResponseFormat {
591        ResponseFormat::Data
592    }
593}
594
595/// 删除文件请求参数
596#[derive(Debug, Clone, Serialize, Deserialize)]
597pub struct DeleteFileRequest {
598    /// 文件token
599    pub file_token: String,
600}
601
602impl DeleteFileRequest {
603    pub fn new(file_token: impl Into<String>) -> Self {
604        Self {
605            file_token: file_token.into(),
606        }
607    }
608}
609
610/// 删除文件响应数据
611#[derive(Debug, Clone, Serialize, Deserialize)]
612pub struct DeleteFileRespData {
613    /// 异步任务ID
614    pub task_id: Option<String>,
615}
616
617impl ApiResponseTrait for DeleteFileRespData {
618    fn data_format() -> ResponseFormat {
619        ResponseFormat::Data
620    }
621}
622
623/// 创建文件快捷方式请求参数
624#[derive(Debug, Clone, Serialize, Deserialize)]
625pub struct CreateFileShortcutRequest {
626    /// 原文件token
627    pub refer_entity: ReferEntity,
628    /// 快捷方式名称
629    pub name: String,
630    /// 父文件夹token
631    pub parent_token: String,
632}
633
634#[derive(Debug, Clone, Serialize, Deserialize)]
635pub struct ReferEntity {
636    /// 原文件类型
637    #[serde(rename = "type")]
638    pub entity_type: String,
639    /// 原文件token
640    pub token: String,
641}
642
643impl CreateFileShortcutRequest {
644    pub fn new(
645        file_type: impl Into<String>,
646        file_token: impl Into<String>,
647        name: impl Into<String>,
648        parent_token: impl Into<String>,
649    ) -> Self {
650        Self {
651            refer_entity: ReferEntity {
652                entity_type: file_type.into(),
653                token: file_token.into(),
654            },
655            name: name.into(),
656            parent_token: parent_token.into(),
657        }
658    }
659}
660
661/// 创建文件快捷方式响应数据
662#[derive(Debug, Clone, Serialize, Deserialize)]
663pub struct CreateFileShortcutRespData {
664    /// 快捷方式token
665    pub token: String,
666    /// 快捷方式链接
667    pub url: String,
668}
669
670impl ApiResponseTrait for CreateFileShortcutRespData {
671    fn data_format() -> ResponseFormat {
672        ResponseFormat::Data
673    }
674}
675
676/// 搜索文件请求参数
677#[derive(Debug, Clone, Serialize, Deserialize)]
678pub struct SearchFilesRequest {
679    /// 搜索关键词
680    pub search_key: String,
681    /// 返回数量
682    pub count: Option<i32>,
683    /// 偏移量
684    pub offset: Option<i32>,
685    /// 所有者ID列表
686    pub owner_ids: Option<Vec<String>>,
687}
688
689impl SearchFilesRequest {
690    pub fn new(search_key: impl Into<String>) -> Self {
691        Self {
692            search_key: search_key.into(),
693            count: None,
694            offset: None,
695            owner_ids: None,
696        }
697    }
698
699    pub fn with_count(mut self, count: i32) -> Self {
700        self.count = Some(count);
701        self
702    }
703
704    pub fn with_offset(mut self, offset: i32) -> Self {
705        self.offset = Some(offset);
706        self
707    }
708
709    pub fn with_owner_ids(mut self, owner_ids: Vec<String>) -> Self {
710        self.owner_ids = Some(owner_ids);
711        self
712    }
713}
714
715/// 搜索文件响应数据
716#[derive(Debug, Clone, Serialize, Deserialize)]
717pub struct SearchFilesRespData {
718    /// 搜索结果文件列表
719    pub files: Vec<SearchFileItem>,
720}
721
722#[derive(Debug, Clone, Serialize, Deserialize)]
723pub struct SearchFileItem {
724    /// 文件token
725    pub token: String,
726    /// 文件名称
727    pub name: String,
728    /// 文件类型
729    #[serde(rename = "type")]
730    pub file_type: String,
731    /// 文件链接
732    pub url: String,
733    /// 拥有者ID
734    pub owner_id: String,
735}
736
737impl ApiResponseTrait for SearchFilesRespData {
738    fn data_format() -> ResponseFormat {
739        ResponseFormat::Data
740    }
741}
742
743/// 分片上传文件-预上传请求参数
744#[derive(Debug, Clone, Serialize, Deserialize)]
745pub struct FileUploadPrepareRequest {
746    /// 文件名称
747    pub file_name: String,
748    /// 父文件夹token
749    pub parent_token: String,
750    /// 文件大小
751    pub size: i64,
752    /// 分片大小(可选)
753    pub block_size: Option<i32>,
754    /// 文件校验和(可选)
755    pub checksum: Option<String>,
756}
757
758impl FileUploadPrepareRequest {
759    pub fn new(file_name: impl Into<String>, parent_token: impl Into<String>, size: i64) -> Self {
760        Self {
761            file_name: file_name.into(),
762            parent_token: parent_token.into(),
763            size,
764            block_size: None,
765            checksum: None,
766        }
767    }
768
769    pub fn with_block_size(mut self, block_size: i32) -> Self {
770        self.block_size = Some(block_size);
771        self
772    }
773
774    pub fn with_checksum(mut self, checksum: impl Into<String>) -> Self {
775        self.checksum = Some(checksum.into());
776        self
777    }
778}
779
780/// 分片上传文件-预上传响应数据
781#[derive(Debug, Clone, Serialize, Deserialize)]
782pub struct FileUploadPrepareRespData {
783    /// 上传事务ID
784    pub upload_id: String,
785    /// 分片大小
786    pub block_size: i32,
787    /// 分片数量
788    pub block_num: i32,
789}
790
791impl ApiResponseTrait for FileUploadPrepareRespData {
792    fn data_format() -> ResponseFormat {
793        ResponseFormat::Data
794    }
795}
796
797/// 分片上传文件-上传分片请求参数
798#[derive(Debug, Clone, Default, Serialize, Deserialize)]
799pub struct FileUploadPartRequest {
800    /// 请求体
801    #[serde(skip)]
802    pub api_req: ApiRequest,
803    /// 上传事务ID
804    upload_id: String,
805    /// 分片序号
806    seq: i32,
807    /// 分片大小
808    size: i32,
809    /// 分片校验和(可选)
810    checksum: Option<String>,
811}
812
813impl FileUploadPartRequest {
814    pub fn builder() -> FileUploadPartRequestBuilder {
815        FileUploadPartRequestBuilder::default()
816    }
817}
818
819/// 分片上传文件-上传分片请求构建器
820#[derive(Default)]
821pub struct FileUploadPartRequestBuilder {
822    request: FileUploadPartRequest,
823}
824
825impl FileUploadPartRequestBuilder {
826    pub fn upload_id(mut self, upload_id: impl Into<String>) -> Self {
827        self.request.upload_id = upload_id.into();
828        self
829    }
830
831    pub fn seq(mut self, seq: i32) -> Self {
832        self.request.seq = seq;
833        self
834    }
835
836    pub fn size(mut self, size: i32) -> Self {
837        self.request.size = size;
838        self
839    }
840
841    pub fn checksum(mut self, checksum: impl Into<String>) -> Self {
842        self.request.checksum = Some(checksum.into());
843        self
844    }
845
846    pub fn file_chunk(mut self, chunk: Vec<u8>) -> Self {
847        self.request.api_req.file = chunk;
848        self
849    }
850
851    pub fn build(mut self) -> FileUploadPartRequest {
852        self.request.api_req.body = serde_json::to_vec(&self.request).unwrap();
853        self.request
854    }
855}
856
857impl_executable_builder_owned!(
858    FileUploadPartRequestBuilder,
859    FileService,
860    FileUploadPartRequest,
861    BaseResponse<FileUploadPartRespData>,
862    upload_part
863);
864
865/// 分片上传文件-上传分片响应数据
866#[derive(Debug, Clone, Serialize, Deserialize)]
867pub struct FileUploadPartRespData {
868    /// 分片ETag
869    pub etag: String,
870}
871
872impl ApiResponseTrait for FileUploadPartRespData {
873    fn data_format() -> ResponseFormat {
874        ResponseFormat::Data
875    }
876}
877
878/// 分片上传文件-完成上传请求参数
879#[derive(Debug, Clone, Serialize, Deserialize)]
880pub struct FileUploadFinishRequest {
881    /// 上传事务ID
882    pub upload_id: String,
883    /// 分片信息列表
884    pub block_infos: Vec<FileBlockInfo>,
885}
886
887#[derive(Debug, Clone, Serialize, Deserialize)]
888pub struct FileBlockInfo {
889    /// 分片ETag
890    pub etag: String,
891    /// 分片序号
892    pub seq: i32,
893}
894
895impl FileUploadFinishRequest {
896    pub fn new(upload_id: impl Into<String>, block_infos: Vec<FileBlockInfo>) -> Self {
897        Self {
898            upload_id: upload_id.into(),
899            block_infos,
900        }
901    }
902}
903
904/// 分片上传文件-完成上传响应数据
905#[derive(Debug, Clone, Serialize, Deserialize)]
906pub struct FileUploadFinishRespData {
907    /// 文件token
908    pub file_token: String,
909}
910
911impl ApiResponseTrait for FileUploadFinishRespData {
912    fn data_format() -> ResponseFormat {
913        ResponseFormat::Data
914    }
915}
916
917/// 创建导入任务请求参数
918#[derive(Debug, Clone, Serialize, Deserialize)]
919pub struct CreateImportTaskRequest {
920    /// 导入文件的token
921    pub file_extension: String,
922    /// 导入文件类型
923    pub file_token: String,
924    /// 导入文件类型
925    #[serde(rename = "type")]
926    pub import_type: String,
927    /// 导入的目标文件夹token
928    pub parent_token: String,
929    /// 导入的文件名称
930    pub file_name: String,
931    /// 导入点类型
932    pub parent_type: String,
933}
934
935impl CreateImportTaskRequest {
936    pub fn new(
937        file_extension: impl Into<String>,
938        file_token: impl Into<String>,
939        import_type: impl Into<String>,
940        parent_token: impl Into<String>,
941        file_name: impl Into<String>,
942        parent_type: impl Into<String>,
943    ) -> Self {
944        Self {
945            file_extension: file_extension.into(),
946            file_token: file_token.into(),
947            import_type: import_type.into(),
948            parent_token: parent_token.into(),
949            file_name: file_name.into(),
950            parent_type: parent_type.into(),
951        }
952    }
953}
954
955/// 创建导入任务响应数据
956#[derive(Debug, Clone, Serialize, Deserialize)]
957pub struct CreateImportTaskRespData {
958    /// 导入任务ID
959    pub ticket: String,
960}
961
962impl ApiResponseTrait for CreateImportTaskRespData {
963    fn data_format() -> ResponseFormat {
964        ResponseFormat::Data
965    }
966}
967
968/// 查询导入任务结果请求参数
969#[derive(Debug, Clone, Serialize, Deserialize)]
970pub struct GetImportTaskRequest {
971    /// 导入任务ID
972    pub ticket: String,
973}
974
975impl GetImportTaskRequest {
976    pub fn new(ticket: impl Into<String>) -> Self {
977        Self {
978            ticket: ticket.into(),
979        }
980    }
981}
982
983/// 查询导入任务结果响应数据
984#[derive(Debug, Clone, Serialize, Deserialize)]
985pub struct GetImportTaskRespData {
986    /// 任务结果
987    pub result: ImportTaskResult,
988}
989
990#[derive(Debug, Clone, Serialize, Deserialize)]
991pub struct ImportTaskResult {
992    /// 任务类型
993    #[serde(rename = "type")]
994    pub task_type: String,
995    /// 任务ID
996    pub ticket: String,
997    /// 任务状态
998    pub job_status: i32,
999    /// 任务错误码
1000    pub job_error_msg: Option<String>,
1001    /// 导入结果
1002    pub token: Option<String>,
1003    /// 导入结果类型
1004    pub url: Option<String>,
1005}
1006
1007impl ApiResponseTrait for GetImportTaskRespData {
1008    fn data_format() -> ResponseFormat {
1009        ResponseFormat::Data
1010    }
1011}