use aws_sdk_s3::primitives::ByteStream;
use tokio::{fs::File, io::AsyncReadExt};
#[derive(Debug, Clone)]
pub struct Operator {
bucket_name: String,
client: aws_sdk_s3::Client,
}
impl Operator {
pub fn new(bucket_name: String, client: aws_sdk_s3::Client) -> Self {
Self {
bucket_name,
client,
}
}
pub async fn upload_file(
&self,
file_name: &str,
mime_type: &str,
file_path: &str,
cache_control: Option<&str>,
) -> Result<(), crate::error::OperationError> {
let mut file = File::open(file_path).await?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer).await?;
match &self
.client
.put_object()
.bucket(&self.bucket_name)
.key(file_name)
.content_type(mime_type)
.cache_control(cache_control.unwrap_or("no-cache"))
.body(ByteStream::from(buffer))
.send()
.await
{
Ok(_) => (),
Err(err) => {
return Err(crate::error::OperationError::AWSSdkS3PutObjectError(
err.to_string(),
))
}
};
Ok(())
}
pub async fn upload_binary(
&self,
file_name: &str,
mime_type: &str,
binary: &[u8],
cache_control: Option<&str>,
) -> Result<(), crate::error::OperationError> {
match &self
.client
.put_object()
.bucket(&self.bucket_name)
.key(file_name)
.content_type(mime_type)
.cache_control(cache_control.unwrap_or("no-cache"))
.body(ByteStream::from(binary.to_vec()))
.send()
.await
{
Ok(_) => (),
Err(err) => {
return Err(crate::error::OperationError::AWSSdkS3PutObjectError(
err.to_string(),
))
}
};
Ok(())
}
pub async fn download(&self, file_name: &str) -> Result<Vec<u8>, crate::error::OperationError> {
let object = match self
.client
.clone()
.get_object()
.bucket(&self.bucket_name)
.key(file_name)
.send()
.await
{
Ok(object) => object,
Err(err) => {
return Err(crate::error::OperationError::AWSSdkS3GetObjectError(
err.to_string(),
))
}
};
let result = match object.body.collect().await {
Ok(result) => result.into_bytes().to_vec(),
Err(err) => return Err(crate::error::OperationError::AWSSdkS3ByteStreamError(err)),
};
Ok(result)
}
pub async fn delete(&self, file_name: &str) -> Result<(), crate::error::OperationError> {
match &self
.client
.delete_object()
.bucket(&self.bucket_name)
.key(file_name)
.send()
.await
{
Ok(_) => (),
Err(err) => {
return Err(crate::error::OperationError::AWSSdkS3DeleteObjectError(
err.to_string(),
))
}
}
Ok(())
}
pub async fn list_objects(&self) -> Result<Vec<String>, crate::error::OperationError> {
let response = &mut self
.client
.list_objects_v2()
.bucket(&self.bucket_name)
.max_keys(10)
.into_paginator()
.send();
let mut objects = Vec::new();
while let Some(result) = response.next().await {
match result {
Ok(output) => {
for object in output.contents() {
objects.push(object.key().unwrap_or("Unknown").to_owned());
}
}
Err(err) => {
return Err(crate::error::OperationError::AWSSdkS3ListObjectsV2Error(
err.to_string(),
))
}
}
}
Ok(objects)
}
}