ibmcloud_cos/
multipartupload.rs1use quick_xml::{de::from_str, se::to_string};
16use reqwest::blocking::Body;
17use serde::{Deserialize, Serialize};
18
19use crate::cos::{check_response, Client, Error};
20
21#[derive(Deserialize, Debug)]
22pub struct InitiateMultipartUploadResult {
23 #[serde(rename = "$unflatten=Bucket")]
24 pub bucket: String,
25 #[serde(rename = "$unflatten=Key")]
26 pub key: String,
27 #[serde(rename = "$unflatten=UploadId")]
28 pub upload_id: String,
29}
30
31#[derive(Deserialize, Serialize, Debug, Clone)]
32pub struct Part {
33 #[serde(rename = "$unflatten=ETag")]
34 pub etag: String,
35 #[serde(rename = "$unflatten=PartNumber")]
36 pub part_number: usize,
37}
38
39#[derive(Deserialize, Serialize, Debug)]
40pub struct CompleteMultipartUpload {
41 #[serde(rename = "Part", default)]
42 pub parts: Vec<Part>,
43}
44
45pub type UploadId = String;
46
47impl Client {
48 pub fn create_multipart_upload(&self, bucket: &str, key: &str) -> Result<UploadId, Error> {
49 let c = &self.client;
50
51 let url = format!("https://{}.{}/{}?uploads", bucket, self.endpoint, key);
52 let response = c
53 .post(url)
54 .header(
55 "Authorization",
56 format!("Bearer {}", self.tm.token()?.access_token),
57 )
58 .send()?;
59
60 let text: String = check_response(response)?.text()?;
61 let mpu_resp: InitiateMultipartUploadResult = from_str(&text)?;
62
63 Ok(mpu_resp.upload_id)
64 }
65
66 pub fn upload_part<T: Into<Body>>(
67 &self,
68 bucket: &str,
69 key: &str,
70 upload_id: &str,
71 sequence_number: usize,
72 chunk: T,
73 ) -> Result<Part, Error> {
74 let c = &self.client;
75
76 let url = format!(
77 "https://{}.{}/{}?partNumber={}&uploadId={}",
78 bucket, self.endpoint, key, sequence_number, upload_id,
79 );
80
81 let resp = c
82 .put(url)
83 .header(
84 "Authorization",
85 format!("Bearer {}", self.tm.token()?.access_token),
86 )
87 .body(chunk)
88 .send()?;
89
90 let resp = check_response(resp)?;
91 let etag = resp.headers()[reqwest::header::ETAG].to_str().unwrap();
92
93 let part = Part {
94 etag: etag.to_string(),
95 part_number: sequence_number,
96 };
97
98 Ok(part)
99 }
100
101 pub fn complete_multipart_upload(
102 &self,
103 bucket: &str,
104 key: &str,
105 upload_id: &str,
106 cmpu: CompleteMultipartUpload,
107 ) -> Result<(), Error> {
108 let c = &self.client;
109
110 let url = format!(
111 "https://{}.{}/{}?uploadId={}",
112 bucket, self.endpoint, key, upload_id
113 );
114
115 let payload = to_string(&cmpu).unwrap();
116
117 let resp = c
118 .post(url)
119 .header(
120 "Authorization",
121 format!("Bearer {}", self.tm.token()?.access_token),
122 )
123 .body(payload)
124 .send()?;
125
126 let _ = check_response(resp)?;
127
128 Ok(())
129 }
130
131 pub fn abort_multipart_upload(
132 &self,
133 bucket: &str,
134 key: &str,
135 upload_id: &str,
136 ) -> Result<(), Error> {
137 let c = &self.client;
138
139 let url = format!(
140 "https://{}.{}/{}?uploadId={}",
141 bucket, self.endpoint, key, upload_id
142 );
143
144 let resp = c
145 .delete(url)
146 .header(
147 "Authorization",
148 format!("Bearer {}", self.tm.token()?.access_token),
149 )
150 .send()?;
151
152 let _ = check_response(resp)?;
153
154 Ok(())
155 }
156}