quoter/src/s3_utils.rs
Untone bc14d86018
Some checks failed
deploy / deploy (push) Failing after 6s
heic-sys
2024-11-13 11:14:53 +03:00

122 lines
4.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use actix_web::error::ErrorInternalServerError;
use aws_sdk_s3::{error::SdkError, primitives::ByteStream, Client as S3Client};
use mime_guess::mime;
use std::str::FromStr;
use infer::get;
/// Загружает файл в S3 хранилище.
pub async fn upload_to_s3(
storj_client: &S3Client,
bucket: &str,
key: &str,
body: Vec<u8>,
content_type: &str,
) -> Result<String, actix_web::Error> {
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<bool, actix_web::Error> {
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(
s3_client: &S3Client,
bucket: &str,
key: &str,
) -> Result<Vec<u8>, actix_web::Error> {
let get_object_output = s3_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.to_lowercase());
}
}
base_key
}
/// список файлов из S3
pub async fn get_s3_filelist(client: &S3Client, bucket: &str) -> Vec<[std::string::String; 2]> {
let mut filenames = 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
if let Some(filename) = parts.pop() {
filenames.push([filename.to_string(), s3_filepath.to_string()]);
}
}
}
}
filenames
}
pub fn detect_mime_type(bytes: &[u8]) -> Option<String> {
let kind = get(bytes)?;
Some(kind.mime_type().to_string())
}
pub fn get_extension_from_mime(mime_type: &str) -> Option<&str> {
match mime_type {
"image/jpeg" => Some("jpg"),
"image/png" => Some("png"),
"image/gif" => Some("gif"),
"image/webp" => Some("webp"),
"image/heic" => Some("heic"),
"image/tiff" => Some("tiff"),
_ => None
}
}