s3/bucket/get.rs
1use crate::bucket::{Bucket, Request};
2use crate::command::Command;
3use crate::error::S3Error;
4use crate::request::RequestImpl;
5use crate::request::ResponseData;
6
7use crate::request::{AsyncWrite, ResponseDataStream};
8
9impl Bucket {
10 /// Gets file from an S3 path.
11 ///
12 /// # Example:
13 ///
14 /// ```rust,no_run
15 /// use s3::bucket::Bucket;
16 /// use s3::creds::Credentials;
17 /// use anyhow::Result;
18 ///
19 /// # #[tokio::main]
20 /// # async fn main() -> Result<()> {
21 ///
22 /// let bucket_name = "rust-s3-test";
23 /// let region = "us-east-1".parse()?;
24 /// let credentials = Credentials::default()?;
25 /// let bucket = Bucket::new(bucket_name, region, credentials)?;
26 ///
27 /// let response_data = bucket.get_object("/test.file").await?;
28 /// # Ok(())
29 /// # }
30 /// ```
31 pub async fn get_object<S: AsRef<str>>(&self, path: S) -> Result<ResponseData, S3Error> {
32 let command = Command::GetObject;
33 let request = RequestImpl::new(self, path.as_ref(), command)?;
34 request.response_data(false).await
35 }
36
37 /// Gets torrent from an S3 path.
38 ///
39 /// # Example:
40 ///
41 /// ```rust,no_run
42 /// use s3::bucket::Bucket;
43 /// use s3::creds::Credentials;
44 /// use anyhow::Result;
45 ///
46 /// # #[tokio::main]
47 /// # async fn main() -> Result<()> {
48 ///
49 /// let bucket_name = "rust-s3-test";
50 /// let region = "us-east-1".parse()?;
51 /// let credentials = Credentials::default()?;
52 /// let bucket = Bucket::new(bucket_name, region, credentials)?;
53 ///
54 /// let response_data = bucket.get_object_torrent("/test.file").await?;
55 /// # Ok(())
56 /// # }
57 /// ```
58 pub async fn get_object_torrent<S: AsRef<str>>(
59 &self,
60 path: S,
61 ) -> Result<ResponseData, S3Error> {
62 let command = Command::GetObjectTorrent;
63 let request = RequestImpl::new(self, path.as_ref(), command)?;
64 request.response_data(false).await
65 }
66
67 /// Gets specified inclusive byte range of file from an S3 path.
68 ///
69 /// # Example:
70 ///
71 /// ```rust,no_run
72 /// use s3::bucket::Bucket;
73 /// use s3::creds::Credentials;
74 /// use anyhow::Result;
75 ///
76 /// # #[tokio::main]
77 /// # async fn main() -> Result<()> {
78 ///
79 /// let bucket_name = "rust-s3-test";
80 /// let region = "us-east-1".parse()?;
81 /// let credentials = Credentials::default()?;
82 /// let bucket = Bucket::new(bucket_name, region, credentials)?;
83 ///
84 /// let response_data = bucket.get_object_range("/test.file", 0, Some(31)).await?;
85 /// #
86 /// # Ok(())
87 /// # }
88 /// ```
89 pub async fn get_object_range<S: AsRef<str>>(
90 &self,
91 path: S,
92 start: u64,
93 end: Option<u64>,
94 ) -> Result<ResponseData, S3Error> {
95 if let Some(end) = end {
96 assert!(start < end);
97 }
98
99 let command = Command::GetObjectRange { start, end };
100 let request = RequestImpl::new(self, path.as_ref(), command)?;
101 request.response_data(false).await
102 }
103
104 /// Stream range of bytes from S3 path to a local file, generic over T: Write.
105 ///
106 /// # Example:
107 ///
108 /// ```rust,no_run
109 /// use s3::bucket::Bucket;
110 /// use s3::creds::Credentials;
111 /// use anyhow::Result;
112 /// use std::fs::File;
113 ///
114 /// # #[tokio::main]
115 /// # async fn main() -> Result<()> {
116 ///
117 /// let bucket_name = "rust-s3-test";
118 /// let region = "us-east-1".parse()?;
119 /// let credentials = Credentials::default()?;
120 /// let bucket = Bucket::new(bucket_name, region, credentials)?;
121 /// let mut output_file = File::create("output_file").expect("Unable to create file");
122 /// let mut async_output_file = tokio::fs::File::create("async_output_file").await.expect("Unable to create file");
123 /// #[cfg(feature = "with-async-std")]
124 /// let mut async_output_file = async_std::fs::File::create("async_output_file").await.expect("Unable to create file");
125 ///
126 /// let start = 0;
127 /// let end = Some(1024);
128 ///
129 /// let status_code = bucket.get_object_range_to_writer("/test.file", start, end, &mut async_output_file).await?;
130 /// #
131 /// # Ok(())
132 /// # }
133 /// ```
134 pub async fn get_object_range_to_writer<T: AsyncWrite + Send + Unpin, S: AsRef<str>>(
135 &self,
136 path: S,
137 start: u64,
138 end: Option<u64>,
139 writer: &mut T,
140 ) -> Result<u16, S3Error> {
141 if let Some(end) = end {
142 assert!(start < end);
143 }
144
145 let command = Command::GetObjectRange { start, end };
146 let request = RequestImpl::new(self, path.as_ref(), command)?;
147 request.response_data_to_writer(writer).await
148 }
149
150 /// Stream file from S3 path to a local file, generic over T: Write.
151 ///
152 /// # Example:
153 ///
154 /// ```rust,no_run
155 /// use s3::bucket::Bucket;
156 /// use s3::creds::Credentials;
157 /// use anyhow::Result;
158 /// use std::fs::File;
159 ///
160 /// # #[tokio::main]
161 /// # async fn main() -> Result<()> {
162 ///
163 /// let bucket_name = "rust-s3-test";
164 /// let region = "us-east-1".parse()?;
165 /// let credentials = Credentials::default()?;
166 /// let bucket = Bucket::new(bucket_name, region, credentials)?;
167 /// let mut output_file = File::create("output_file").expect("Unable to create file");
168 /// let mut async_output_file = tokio::fs::File::create("async_output_file").await.expect("Unable to create file");
169 /// #[cfg(feature = "with-async-std")]
170 /// let mut async_output_file = async_std::fs::File::create("async_output_file").await.expect("Unable to create file");
171 ///
172 /// let status_code = bucket.get_object_to_writer("/test.file", &mut async_output_file).await?;
173 /// #
174 /// # Ok(())
175 /// # }
176 /// ```
177 pub async fn get_object_to_writer<T: AsyncWrite + Send + Unpin, S: AsRef<str>>(
178 &self,
179 path: S,
180 writer: &mut T,
181 ) -> Result<u16, S3Error> {
182 let command = Command::GetObject;
183 let request = RequestImpl::new(self, path.as_ref(), command)?;
184 request.response_data_to_writer(writer).await
185 }
186
187 /// Stream file from S3 path to a local file using an async stream.
188 ///
189 /// # Example
190 ///
191 /// ```rust,no_run
192 /// use s3::bucket::Bucket;
193 /// use s3::creds::Credentials;
194 /// use anyhow::Result;
195 /// use tokio_stream::StreamExt;
196 /// use tokio::io::AsyncWriteExt;
197 ///
198 /// # #[tokio::main]
199 /// # async fn main() -> Result<()> {
200 ///
201 /// let bucket_name = "rust-s3-test";
202 /// let region = "us-east-1".parse()?;
203 /// let credentials = Credentials::default()?;
204 /// let bucket = Bucket::new(bucket_name, region, credentials)?;
205 /// let path = "path";
206 ///
207 /// let mut response_data_stream = bucket.get_object_stream(path).await?;
208 ///
209 /// let mut async_output_file = tokio::fs::File::create("async_output_file").await.expect("Unable to create file");
210 ///
211 /// while let Some(chunk) = response_data_stream.bytes().next().await {
212 /// async_output_file.write_all(&chunk.unwrap()).await?;
213 /// }
214 ///
215 /// #
216 /// # Ok(())
217 /// # }
218 /// ```
219 pub async fn get_object_stream<S: AsRef<str>>(
220 &self,
221 path: S,
222 ) -> Result<ResponseDataStream, S3Error> {
223 let command = Command::GetObject;
224 let request = RequestImpl::new(self, path.as_ref(), command)?;
225 request.response_data_to_stream().await
226 }
227
228 /// Retrieve an S3 object list of tags.
229 ///
230 /// # Example:
231 ///
232 /// ```no_run
233 /// use s3::bucket::Bucket;
234 /// use s3::creds::Credentials;
235 /// use anyhow::Result;
236 ///
237 /// # #[tokio::main]
238 /// # async fn main() -> Result<()> {
239 ///
240 /// let bucket_name = "rust-s3-test";
241 /// let region = "us-east-1".parse()?;
242 /// let credentials = Credentials::default()?;
243 /// let bucket = Bucket::new(bucket_name, region, credentials)?;
244 ///
245 /// let response_data = bucket.get_object_tagging("/test.file").await?;
246 /// #
247 /// # Ok(())
248 /// # }
249 /// ```
250 pub async fn get_object_tagging<S: AsRef<str>>(
251 &self,
252 path: S,
253 ) -> Result<(Vec<crate::Tag>, u16), S3Error> {
254 let command = Command::GetObjectTagging {};
255 let request = RequestImpl::new(self, path.as_ref(), command)?;
256 let result = request.response_data(false).await?;
257
258 let mut tags = Vec::new();
259
260 if result.status_code() == 200 {
261 let result_string = String::from_utf8_lossy(result.as_slice());
262
263 // Add namespace if it doesn't exist
264 let ns = "http://s3.amazonaws.com/doc/2006-03-01/";
265 let result_string = if let Err(minidom::Error::MissingNamespace) =
266 result_string.parse::<minidom::Element>()
267 {
268 result_string
269 .replace("<Tagging>", &format!("<Tagging xmlns=\"{}\">", ns))
270 .into()
271 } else {
272 result_string
273 };
274
275 if let Ok(tagging) = result_string.parse::<minidom::Element>() {
276 for tag_set in tagging.children() {
277 if tag_set.is("TagSet", ns) {
278 for tag in tag_set.children() {
279 if tag.is("Tag", ns) {
280 let key = if let Some(element) = tag.get_child("Key", ns) {
281 element.text()
282 } else {
283 "Could not parse Key from Tag".to_string()
284 };
285 let value = if let Some(element) = tag.get_child("Value", ns) {
286 element.text()
287 } else {
288 "Could not parse Values from Tag".to_string()
289 };
290 tags.push(crate::Tag { key, value });
291 }
292 }
293 }
294 }
295 }
296 }
297
298 Ok((tags, result.status_code()))
299 }
300}