quoter/src/handlers/upload.rs
2024-10-22 09:38:30 +03:00

78 lines
3.0 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_multipart::Multipart;
use actix_web::{web, HttpRequest, HttpResponse, Result};
use crate::app_state::AppState;
use crate::auth::{get_id_by_token, user_added_file};
use crate::s3_utils::{generate_key_with_extension, upload_to_s3};
use futures::TryStreamExt;
use crate::handlers::MAX_WEEK_BYTES;
/// Обработчик для аплоада файлов.
pub async fn upload_handler(
req: HttpRequest,
mut payload: Multipart,
state: web::Data<AppState>,
) -> Result<HttpResponse, actix_web::Error> {
// Получаем токен из заголовка авторизации
let token = req
.headers()
.get("Authorization")
.and_then(|header_value| header_value.to_str().ok());
if token.is_none() {
return Err(actix_web::error::ErrorUnauthorized("Unauthorized")); // Если токен отсутствует, возвращаем ошибку
}
let user_id = get_id_by_token(token.unwrap()).await?;
// Получаем текущую квоту пользователя
let this_week_amount: u64 = state.get_or_create_quota(&user_id).await.unwrap_or(0);
let mut body = "ok".to_string();
while let Ok(Some(field)) = payload.try_next().await {
let mut field = field;
let content_type = field.content_type().unwrap().to_string();
let file_name = field
.content_disposition()
.unwrap()
.get_filename()
.map(|f| f.to_string());
if let Some(name) = file_name {
let mut file_bytes = Vec::new();
let mut file_size: u64 = 0;
// Читаем данные файла
while let Ok(Some(chunk)) = field.try_next().await {
file_size += chunk.len() as u64;
file_bytes.extend_from_slice(&chunk);
}
// Проверяем, что добавление файла не превышает лимит квоты
if this_week_amount + file_size > MAX_WEEK_BYTES {
return Err(actix_web::error::ErrorUnauthorized("Quota exceeded"));
// Квота превышена
}
// инкрементируем квоту пользователя
let _ = state.increment_uploaded_bytes(&user_id, file_size).await?;
// Определяем правильное расширение и ключ для S3
body = generate_key_with_extension(name, content_type.to_owned());
// Загружаем файл в S3
upload_to_s3(
&state.storj_client,
&state.storj_bucket,
&body,
file_bytes,
&content_type,
)
.await?;
// Сохраняем информацию о загруженном файле для пользователя
user_added_file(&mut state.redis.clone(), &user_id, &body).await?;
}
}
Ok(HttpResponse::Ok().body(body))
}