use actix_web::error::ErrorInternalServerError; use aws_sdk_s3::{error::SdkError, primitives::ByteStream, Client as S3Client}; use mime_guess::mime; use std::str::FromStr; /// Загружает файл в S3 хранилище. pub async fn upload_to_s3( storj_client: &S3Client, bucket: &str, key: &str, body: Vec, content_type: &str, ) -> Result { let body_stream = ByteStream::from(body); // Преобразуем тело файла в поток байтов storj_client .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( s3_client: &S3Client, bucket: &str, filepath: &str, ) -> Result { match s3_client.head_object().bucket(bucket).key(filepath).send().await { 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( storj_client: &S3Client, bucket: &str, key: &str, ) -> Result, actix_web::Error> { let get_object_output = storj_client .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 } /// список файлов из 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::>(); // Explicit type annotation let filename = parts.pop().unwrap(); let mut filename_parts = filename.split('.').collect::>(); let _ext = filename_parts.pop().unwrap(); let filekey = filename_parts.pop().unwrap(); filekeys.push([filekey.to_string(), s3_filepath.to_string()]); } } } filekeys }