aliyun_oss_rs/object/
multipart_init_upload.rs1use crate::common::body_to_bytes;
2use crate::{
3 common::{
4 Acl, CacheControl, ContentDisposition, StorageClass, invalid_metadata_key, url_encode,
5 },
6 error::{Error, normal_error},
7 request::{Oss, OssRequest},
8};
9use http::{Method, header};
10use serde_derive::Deserialize;
11use std::collections::HashMap;
12
13#[derive(Debug, Deserialize)]
15#[serde(rename_all = "PascalCase")]
16struct InitiateMultipartUploadResult {
17 upload_id: String,
18}
19
20pub struct InitUpload {
24 req: OssRequest,
25 tags: HashMap<String, String>,
26}
27impl InitUpload {
28 pub(super) fn new(oss: Oss) -> Self {
29 let mut req = OssRequest::new(oss, Method::POST);
30 req.insert_query("uploads", "");
31 InitUpload {
32 req,
33 tags: HashMap::new(),
34 }
35 }
36 pub fn set_mime(mut self, mime: impl ToString) -> Self {
40 self.req.insert_header(header::CONTENT_TYPE, mime);
41 self
42 }
43 pub fn set_acl(mut self, acl: Acl) -> Self {
45 self.req.insert_header("x-oss-object-acl", acl);
46 self
47 }
48 pub fn set_storage_class(mut self, storage_class: StorageClass) -> Self {
50 self.req.insert_header("x-oss-storage-class", storage_class);
51 self
52 }
53 pub fn set_cache_control(mut self, cache_control: CacheControl) -> Self {
55 self.req.insert_header(header::CACHE_CONTROL, cache_control);
56 self
57 }
58 pub fn set_content_disposition(mut self, content_disposition: ContentDisposition) -> Self {
60 self.req
61 .insert_header(header::CONTENT_DISPOSITION, content_disposition);
62 self
63 }
64 pub fn forbid_overwrite(mut self) -> Self {
66 self.req.insert_header("x-oss-forbid-overwrite", "true");
67 self
68 }
69 pub fn set_meta(mut self, key: impl ToString, value: impl ToString) -> Self {
73 let key = key.to_string();
74 if !invalid_metadata_key(&key) {
75 self.req
76 .insert_header(format!("x-oss-meta-{}", key.to_string()), value);
77 }
78 self
79 }
80 pub fn set_tagging(mut self, key: impl ToString, value: impl ToString) -> Self {
82 self.tags.insert(key.to_string(), value.to_string());
83 self
84 }
85 pub async fn send(mut self) -> Result<String, Error> {
87 let tags = self
89 .tags
90 .into_iter()
91 .map(|(key, value)| {
92 if value.is_empty() {
93 url_encode(&key.to_string())
94 } else {
95 format!(
96 "{}={}",
97 url_encode(&key.to_string()),
98 url_encode(&value.to_string())
99 )
100 }
101 })
102 .collect::<Vec<_>>()
103 .join("&");
104 if !tags.is_empty() {
105 self.req.insert_header("x-oss-tagging", tags);
106 }
107 let response = self.req.send_to_oss()?.await?;
109 let status_code = response.status();
111 match status_code {
112 code if code.is_success() => {
113 let response_bytes = body_to_bytes(response.into_body())
114 .await
115 .map_err(|_| Error::OssInvalidResponse(None))?;
116 let result: InitiateMultipartUploadResult =
117 serde_xml_rs::from_reader(&*response_bytes)
118 .map_err(|_| Error::OssInvalidResponse(Some(response_bytes)))?;
119 Ok(result.upload_id)
120 }
121 _ => Err(normal_error(response).await),
122 }
123 }
124}