This commit is contained in:
parent
c5038dd610
commit
4a1f985cce
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "discoursio-quoter"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -4,7 +4,7 @@ use aws_sdk_s3::{config::Credentials, Client as S3Client};
|
|||
use redis::{aio::MultiplexedConnection, AsyncCommands, Client as RedisClient};
|
||||
use std::{env, time::Duration};
|
||||
use tokio::time::interval;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use crate::s3_utils::check_file_exists;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -110,12 +110,13 @@ impl AppState {
|
|||
for object in objects.iter() {
|
||||
if let Some(key) = &object.key {
|
||||
let parts: Vec<&str> = key.split('.').collect();
|
||||
if parts.len() > 1 && !parts.last().unwrap().contains('/') {
|
||||
let filename = parts[0..parts.len()-1].join(".");
|
||||
file_list.entry(filename).or_insert(key.clone());
|
||||
} else {
|
||||
file_list.entry(key.to_string()).or_insert(key.clone());
|
||||
let filename = parts.first().unwrap_or(&"");
|
||||
let ext = parts.get(1).unwrap_or(&"");
|
||||
if ext.contains('/') {
|
||||
continue;
|
||||
}
|
||||
let filename_with_extension = format!("{}.{}", filename, ext);
|
||||
file_list.insert(filename_with_extension, key.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,25 +151,25 @@ impl AppState {
|
|||
}
|
||||
|
||||
/// Сохраняет маппинг старого пути из AWS S3 на новый путь в Storj S3.
|
||||
async fn save_path_by_filekey(
|
||||
async fn save_path_by_filename_with_extension(
|
||||
&self,
|
||||
filekey: &str,
|
||||
filename_with_extension: &str,
|
||||
path: &str,
|
||||
) -> Result<(), actix_web::Error> {
|
||||
let mut redis = self.redis.clone();
|
||||
// Храним маппинг в формате Hash: old_path -> new_path
|
||||
redis
|
||||
.hset::<_, &str, &str, ()>(PATH_MAPPING_KEY, filekey, path)
|
||||
.hset::<_, &str, &str, ()>(PATH_MAPPING_KEY, filename_with_extension, path)
|
||||
.await
|
||||
.map_err(|_| ErrorInternalServerError("Failed to save path mapping in Redis"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Получает путь в хранилище из ключа (имени файла) в Redis.
|
||||
pub async fn get_path(&self, filekey: &str) -> Result<Option<String>, actix_web::Error> {
|
||||
pub async fn get_path(&self, filename_with_extension: &str) -> Result<Option<String>, actix_web::Error> {
|
||||
let mut redis = self.redis.clone();
|
||||
let new_path: Option<String> = redis
|
||||
.hget(PATH_MAPPING_KEY, filekey)
|
||||
.hget(PATH_MAPPING_KEY, filename_with_extension)
|
||||
.await
|
||||
.map_err(|_| ErrorInternalServerError("Failed to get path mapping from Redis"))?;
|
||||
Ok(new_path)
|
||||
|
@ -186,35 +187,38 @@ impl AppState {
|
|||
for object in objects {
|
||||
if let Some(key) = object.key {
|
||||
// Получаем имя файла с расширением
|
||||
let [filename, ext] = key.split('.').collect::<Vec<&str>>();
|
||||
let parts: Vec<&str> = key.split('.').collect();
|
||||
let filename = parts.first().unwrap_or(&"");
|
||||
let ext = parts.get(1).unwrap_or(&"");
|
||||
if ext.contains('/') {
|
||||
continue;
|
||||
}
|
||||
let filename_with_extension = format!("{}.{}", filename, ext);
|
||||
|
||||
if filename.is_empty() {
|
||||
eprint!("Пустое имя файла {}", key);
|
||||
eprint!("[ERROR] empty filename: {}", key);
|
||||
} else {
|
||||
// Проверяем, существует ли файл на Storj S3
|
||||
match check_file_exists(&self.s3_client, &self.s3_bucket, filename)
|
||||
match check_file_exists(&self.s3_client, &self.s3_bucket, &filename_with_extension)
|
||||
.await
|
||||
{
|
||||
Ok(false) => {
|
||||
// Сохраняем маппинг пути
|
||||
if let Err(e) =
|
||||
self.save_path_by_filekey(filename, &key).await
|
||||
self.save_path_by_filename_with_extension(&filename_with_extension, &key).await
|
||||
{
|
||||
eprintln!(
|
||||
"[ОШИБКА СОХРАНЕНИЯ] {}: {:?}",
|
||||
filename_with_extension, e
|
||||
);
|
||||
eprintln!("[ERROR] save {}: {:?}", key, e);
|
||||
} else {
|
||||
println!("{}", filename_with_extension);
|
||||
println!("{}", key);
|
||||
}
|
||||
}
|
||||
Ok(true) => {
|
||||
println!("Файл {} уже существует в Storj.", filename);
|
||||
println!("Already exists in Storj: {}", filename_with_extension);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
"Ошибка при проверке файла {} на Storj: {:?}",
|
||||
filename, e
|
||||
"[ERROR] check {}: {:?}",
|
||||
filename_with_extension, e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -222,11 +226,11 @@ impl AppState {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
println!("Список файлов в AWS S3 пуст.");
|
||||
println!("AWS S3 file list is empty.");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Не удалось получить список файлов из AWS S3: {:?}", e);
|
||||
eprintln!("[ERROR] get AWS S3 file list: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,14 +17,14 @@ use crate::thumbnail::{
|
|||
pub const MAX_WEEK_BYTES: u64 = 2 * 1024 * 1024 * 1024;
|
||||
|
||||
/// Функция для обслуживания файла по заданному пути.
|
||||
async fn serve_file(file_key: &str, state: &AppState) -> Result<HttpResponse, actix_web::Error> {
|
||||
async fn serve_file(filename_with_extension: &str, state: &AppState) -> Result<HttpResponse, actix_web::Error> {
|
||||
// Проверяем наличие файла в Storj S3
|
||||
if !check_file_exists(&state.s3_client, &state.s3_bucket, file_key).await? {
|
||||
warn!("{}", file_key);
|
||||
if !check_file_exists(&state.s3_client, &state.s3_bucket, filename_with_extension).await? {
|
||||
warn!("{}", filename_with_extension);
|
||||
return Err(ErrorInternalServerError("File not found in S3"));
|
||||
}
|
||||
|
||||
let checked_filekey = state.get_path(file_key).await.unwrap().unwrap();
|
||||
let checked_filekey = state.get_path(filename_with_extension).await.unwrap().unwrap();
|
||||
|
||||
// Получаем объект из Storj S3
|
||||
let get_object_output = state
|
||||
|
@ -43,7 +43,7 @@ async fn serve_file(file_key: &str, state: &AppState) -> Result<HttpResponse, ac
|
|||
.map_err(|_| ErrorInternalServerError("Failed to read object body"))?;
|
||||
|
||||
let data_bytes = data.into_bytes();
|
||||
let mime_type = MimeGuess::from_path(file_key).first_or_octet_stream(); // Определяем MIME-тип файла
|
||||
let mime_type = MimeGuess::from_path(filename_with_extension).first_or_octet_stream(); // Определяем MIME-тип файла
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(mime_type.as_ref())
|
||||
|
@ -126,7 +126,7 @@ pub async fn proxy_handler(
|
|||
path: web::Path<String>,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
info!("proxy_handler вызван с путем: {}", path);
|
||||
info!("proxy_handler: {}", path);
|
||||
|
||||
let requested_path = match state.get_path(&path).await {
|
||||
Ok(Some(path)) => path,
|
||||
|
|
Loading…
Reference in New Issue
Block a user