aliyun_oss_rs/object/
multipart_copyto_part.rs

1use crate::{
2    common::format_gmt,
3    error::{Error, normal_error},
4    request::{Oss, OssRequest},
5};
6use http::Method;
7use time::OffsetDateTime;
8
9/// Initialize a multipart upload part
10///
11/// See the [Alibaba Cloud documentation](https://help.aliyun.com/document_detail/31994.html) for details
12pub struct CopyToPart {
13    req: OssRequest,
14}
15impl CopyToPart {
16    pub(super) fn new(
17        oss: Oss,
18        part_number: u32,
19        upload_id: impl ToString,
20        copy_source: impl ToString,
21    ) -> Self {
22        let mut req = OssRequest::new(oss, Method::PUT);
23        req.insert_query("partNumber", part_number);
24        req.insert_query("uploadId", upload_id);
25        req.insert_header("x-oss-copy-source", copy_source);
26        CopyToPart { req }
27    }
28    /// Set the source file copy range
29    ///
30    /// By default, the entire file is copied; byte indexing starts at 0
31    pub fn set_source_range(mut self, start: usize, end: Option<usize>) -> Self {
32        self.req.insert_header(
33            "x-oss-copy-source-range",
34            format!(
35                "bytes={}-{}",
36                start,
37                end.map(|v| v.to_string()).unwrap_or_else(|| String::new())
38            ),
39        );
40        self
41    }
42    /// If the specified time is earlier than the file's actual modification time, the copy proceeds.
43    ///
44    pub fn set_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self {
45        self.req.insert_header(
46            "x-oss-copy-source-if-modified-since",
47            format_gmt(if_modified_since),
48        );
49        self
50    }
51    /// If the specified time is equal to or later than the file's actual modification time, the copy proceeds.
52    ///
53    pub fn set_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self {
54        self.req.insert_header(
55            "x-oss-copy-source-if-unmodified-since",
56            format_gmt(if_unmodified_since),
57        );
58        self
59    }
60    /// Copy the source file only if its ETag matches the value you provide.
61    ///
62    /// The ETag is used to verify whether the data has changed; you can use it to check data integrity.
63    pub fn set_if_match(mut self, if_match: impl ToString) -> Self {
64        self.req
65            .insert_header("x-oss-copy-source-if-match", if_match);
66        self
67    }
68    /// Copy the source file only if its ETag does not match the value you provide.
69    ///
70    /// The ETag is used to verify whether the data has changed; you can use it to check data integrity.
71    pub fn set_if_none_match(mut self, if_none_match: impl ToString) -> Self {
72        self.req
73            .insert_header("x-oss-copy-source-if-none-match", if_none_match);
74        self
75    }
76    /// Copy object content to a part
77    ///
78    /// Returns the ETag
79    pub async fn send(self) -> Result<String, Error> {
80        // Upload file
81        let response = self.req.send_to_oss()?.await?;
82        // Parse the response
83        let status_code = response.status();
84        match status_code {
85            code if code.is_success() => {
86                let e_tag = response
87                    .headers()
88                    .get("ETag")
89                    .map(|v| String::from_utf8(v.as_bytes().to_vec()).ok())
90                    .flatten()
91                    .unwrap_or_else(|| String::new());
92                Ok(e_tag)
93            }
94            _ => Err(normal_error(response).await),
95        }
96    }
97}