onspring/endpoints/
files.rs1use reqwest::Method;
2
3use crate::client::OnspringClient;
4use crate::error::Result;
5use crate::models::{CreatedWithIdResponse, FileInfo, FileResponse, SaveFileRequest};
6
7impl OnspringClient {
8 pub async fn get_file_info(
10 &self,
11 record_id: i32,
12 field_id: i32,
13 file_id: i32,
14 ) -> Result<FileInfo> {
15 let path = format!(
16 "/Files/recordId/{}/fieldId/{}/fileId/{}",
17 record_id, field_id, file_id
18 );
19 self
20 .request(Method::GET, &path, &[], Option::<&()>::None)
21 .await
22 }
23
24 pub async fn get_file(
26 &self,
27 record_id: i32,
28 field_id: i32,
29 file_id: i32,
30 ) -> Result<FileResponse> {
31 let path = format!(
32 "/Files/recordId/{}/fieldId/{}/fileId/{}/file",
33 record_id, field_id, file_id
34 );
35 let (_status, headers, data) = self.request_bytes(Method::GET, &path, &[]).await?;
36
37 let content_type = headers
38 .get("content-type")
39 .and_then(|v| v.to_str().ok())
40 .map(String::from);
41
42 let file_name = headers
43 .get("content-disposition")
44 .and_then(|v| v.to_str().ok())
45 .and_then(|v| {
46 v.split("filename=")
47 .nth(1)
48 .map(|s| s.trim_matches('"').to_string())
49 });
50
51 Ok(FileResponse {
52 content_type,
53 file_name,
54 data,
55 })
56 }
57
58 pub async fn upload_file(&self, request: SaveFileRequest) -> Result<CreatedWithIdResponse> {
60 let file_part = reqwest::multipart::Part::bytes(request.file_data)
61 .file_name(request.file_name)
62 .mime_str(&request.content_type)
63 .map_err(|e| crate::error::OnspringError::InvalidArgument(e.to_string()))?;
64
65 let mut form = reqwest::multipart::Form::new()
66 .text("RecordId", request.record_id.to_string())
67 .text("FieldId", request.field_id.to_string())
68 .part("File", file_part);
69
70 if let Some(notes) = request.notes {
71 form = form.text("Notes", notes);
72 }
73 if let Some(date) = request.modified_date {
74 form = form.text("ModifiedDate", date.to_rfc3339());
75 }
76
77 self.request_multipart("/Files", form).await
78 }
79
80 pub async fn delete_file(&self, record_id: i32, field_id: i32, file_id: i32) -> Result<()> {
82 let path = format!(
83 "/Files/recordId/{}/fieldId/{}/fileId/{}",
84 record_id, field_id, file_id
85 );
86 self
87 .request_no_content(Method::DELETE, &path, &[], Option::<&()>::None)
88 .await
89 }
90}