2024-08-31 00:32:37 +00:00
|
|
|
|
use actix_web::error::ErrorInternalServerError;
|
|
|
|
|
use aws_sdk_s3::{error::SdkError, primitives::ByteStream, Client as S3Client};
|
|
|
|
|
use mime_guess::mime;
|
2024-09-23 15:16:47 +00:00
|
|
|
|
use std::str::FromStr;
|
2024-08-31 00:32:37 +00:00
|
|
|
|
|
|
|
|
|
/// Загружает файл в S3 хранилище.
|
|
|
|
|
pub async fn upload_to_s3(
|
2024-10-22 06:38:30 +00:00
|
|
|
|
storj_client: &S3Client,
|
2024-08-31 00:32:37 +00:00
|
|
|
|
bucket: &str,
|
|
|
|
|
key: &str,
|
|
|
|
|
body: Vec<u8>,
|
|
|
|
|
content_type: &str,
|
|
|
|
|
) -> Result<String, actix_web::Error> {
|
|
|
|
|
let body_stream = ByteStream::from(body); // Преобразуем тело файла в поток байтов
|
2024-10-22 06:38:30 +00:00
|
|
|
|
storj_client
|
2024-08-31 00:32:37 +00:00
|
|
|
|
.put_object()
|
|
|
|
|
.bucket(bucket)
|
|
|
|
|
.key(key)
|
|
|
|
|
.body(body_stream)
|
|
|
|
|
.content_type(content_type)
|
|
|
|
|
.send()
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|_| ErrorInternalServerError("Failed to upload file to S3"))?; // Загрузка файла в S3
|
|
|
|
|
|
|
|
|
|
Ok(key.to_string()) // Возвращаем ключ файла
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Проверяет, существует ли файл в S3.
|
|
|
|
|
pub async fn check_file_exists(
|
2024-10-22 09:24:47 +00:00
|
|
|
|
s3_client: &S3Client,
|
2024-08-31 00:32:37 +00:00
|
|
|
|
bucket: &str,
|
2024-10-22 09:24:47 +00:00
|
|
|
|
filepath: &str,
|
2024-08-31 00:32:37 +00:00
|
|
|
|
) -> Result<bool, actix_web::Error> {
|
2024-10-22 09:24:47 +00:00
|
|
|
|
match s3_client.head_object().bucket(bucket).key(filepath).send().await {
|
2024-08-31 00:32:37 +00:00
|
|
|
|
Ok(_) => Ok(true), // Файл найден
|
|
|
|
|
Err(SdkError::ServiceError(service_error)) if service_error.err().is_not_found() => {
|
|
|
|
|
Ok(false) // Файл не найден
|
|
|
|
|
}
|
|
|
|
|
Err(e) => Err(ErrorInternalServerError(e.to_string())), // Ошибка при проверке
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Загружает файл из S3.
|
|
|
|
|
pub async fn load_file_from_s3(
|
2024-10-22 06:38:30 +00:00
|
|
|
|
storj_client: &S3Client,
|
2024-08-31 00:32:37 +00:00
|
|
|
|
bucket: &str,
|
|
|
|
|
key: &str,
|
|
|
|
|
) -> Result<Vec<u8>, actix_web::Error> {
|
2024-10-22 06:38:30 +00:00
|
|
|
|
let get_object_output = storj_client
|
2024-08-31 00:32:37 +00:00
|
|
|
|
.get_object()
|
|
|
|
|
.bucket(bucket)
|
|
|
|
|
.key(key)
|
|
|
|
|
.send()
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|_| ErrorInternalServerError("Failed to get object from S3"))?;
|
|
|
|
|
|
|
|
|
|
let data: aws_sdk_s3::primitives::AggregatedBytes = get_object_output
|
|
|
|
|
.body
|
|
|
|
|
.collect()
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|_| ErrorInternalServerError("Failed to read object body"))?;
|
|
|
|
|
|
|
|
|
|
Ok(data.to_vec())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Генерирует ключ с правильным расширением на основе MIME-типа.
|
|
|
|
|
pub fn generate_key_with_extension(base_key: String, mime_type: String) -> String {
|
|
|
|
|
let mime: mime::Mime =
|
|
|
|
|
mime::Mime::from_str(&mime_type).unwrap_or(mime::APPLICATION_OCTET_STREAM);
|
|
|
|
|
if let Some(extensions) = mime_guess::get_mime_extensions_str(mime.as_ref()) {
|
|
|
|
|
if let Some(extension) = extensions.first() {
|
|
|
|
|
return format!("{}.{}", base_key, extension);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
base_key
|
|
|
|
|
}
|
2024-10-22 09:24:47 +00:00
|
|
|
|
|
|
|
|
|
/// список файлов из S3
|
|
|
|
|
pub async fn get_s3_filelist(client: &S3Client, bucket: &str) -> Vec<[std::string::String; 2]> {
|
|
|
|
|
let mut filekeys = Vec::new();
|
|
|
|
|
// Запрашиваем список файлов из S3
|
|
|
|
|
let list_objects_v2 = client.list_objects_v2();
|
|
|
|
|
let list_response = list_objects_v2
|
|
|
|
|
.bucket(bucket)
|
|
|
|
|
.send()
|
|
|
|
|
.await
|
|
|
|
|
.expect("Failed to list files from Storj");
|
|
|
|
|
|
|
|
|
|
if let Some(objects) = list_response.contents {
|
|
|
|
|
for object in objects.iter() {
|
|
|
|
|
if let Some(s3_filepath) = &object.key {
|
|
|
|
|
let filepath = match s3_filepath.ends_with("/webp") {
|
|
|
|
|
true => &s3_filepath.replace("/webp", ""),
|
|
|
|
|
false => s3_filepath,
|
|
|
|
|
};
|
|
|
|
|
let mut parts = filepath.split('/').collect::<Vec<&str>>(); // Explicit type annotation
|
|
|
|
|
let filename = parts.pop().unwrap();
|
|
|
|
|
let mut filename_parts = filename.split('.').collect::<Vec<&str>>();
|
|
|
|
|
let _ext = filename_parts.pop().unwrap();
|
|
|
|
|
let filekey = filename_parts.pop().unwrap();
|
|
|
|
|
|
|
|
|
|
filekeys.push([filekey.to_string(), s3_filepath.to_string()]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
filekeys
|
|
|
|
|
}
|