fix-thumb3
This commit is contained in:
parent
cbb8025a0c
commit
76805803b4
143
src/thumbnail.rs
143
src/thumbnail.rs
|
@ -1,6 +1,6 @@
|
|||
use actix_web::error::ErrorInternalServerError;
|
||||
use image::{imageops::FilterType, DynamicImage, ImageFormat};
|
||||
use log::warn;
|
||||
use log::{warn, error};
|
||||
use std::{collections::HashMap, io::Cursor};
|
||||
|
||||
use crate::{app_state::AppState, s3_utils::upload_to_s3};
|
||||
|
@ -13,74 +13,47 @@ pub const THUMB_WIDTHS: [u32; 7] = [10, 40, 110, 300, 600, 800, 1400];
|
|||
/// - "unsafe/1440x/production/image/439efaa0-816f-11ef-b201-439da98539bc.jpg" -> ("439efaa0-816f-11ef-b201-439da98539bc", 1440, "jpg")
|
||||
/// - "unsafe/production/image/5627e002-0c53-11ee-9565-0242ac110006.png" -> ("5627e002-0c53-11ee-9565-0242ac110006", 0, "png")
|
||||
/// - "unsafe/development/image/439efaa0-816f-11ef-b201-439da98539bc.jpg/webp" -> ("439efaa0-816f-11ef-b201-439da98539bc", 0, "webp")
|
||||
/// - "059ab1e0-66c7-11e9-adda-e3ab2ab4e37e_800.jpg" -> ("059ab1e0-66c7-11e9-adda-e3ab2ab4e37e", 800, "jpg")
|
||||
pub fn parse_file_path(requested_path: &str) -> (String, u32, String) {
|
||||
let mut path = requested_path.to_string();
|
||||
if requested_path.ends_with("/webp") {
|
||||
// Удаляем /webp в конце, если есть
|
||||
if path.ends_with("/webp") {
|
||||
path = path.replace("/webp", "");
|
||||
}
|
||||
|
||||
// Получаем последнюю часть пути (имя файла с расширением)
|
||||
let filename = path.split('/').last().unwrap_or(&path);
|
||||
|
||||
let path_parts: Vec<&str> = path.split('/').collect();
|
||||
let mut extension = String::new();
|
||||
// Разделяем имя файла и расширение
|
||||
let (mut base_filename, extension) = filename
|
||||
.rsplit_once('.')
|
||||
.unwrap_or((filename, ""));
|
||||
|
||||
// Инициализируем переменные
|
||||
let mut width = 0;
|
||||
let mut base_filename = String::new();
|
||||
|
||||
// Получаем последнюю часть пути (имя файла)
|
||||
if let Some(last_part) = path_parts.last() {
|
||||
// Разделяем имя файла и расширение
|
||||
if let Some((name, ext)) = last_part.rsplit_once('.') {
|
||||
extension = ext.to_string();
|
||||
base_filename = name.to_string();
|
||||
} else {
|
||||
base_filename = last_part.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем наличие ширины в пути
|
||||
for part in path_parts.iter() {
|
||||
if part.ends_with('x') {
|
||||
if let Ok(w) = part.trim_end_matches('x').parse::<u32>() {
|
||||
width = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Извлечение ширины из base_filename, если она есть
|
||||
if let Some((name_part, width_str)) = base_filename.rsplit_once('_') {
|
||||
|
||||
// Проверяем наличие ширины в имени файла
|
||||
if let Some((name, width_str)) = base_filename.rsplit_once('_') {
|
||||
if let Ok(w) = width_str.parse::<u32>() {
|
||||
width = w;
|
||||
base_filename = name_part.to_string();
|
||||
base_filename = name;
|
||||
}
|
||||
}
|
||||
|
||||
// Проверка на старую ширину в путях, начинающихся с "unsafe"
|
||||
if path.starts_with("unsafe") && width == 0 {
|
||||
if path_parts.len() >= 2 {
|
||||
if let Some(old_width_str) = path_parts.get(1) { // Получаем второй элемент
|
||||
let old_width_str = old_width_str.trim_end_matches('x');
|
||||
if let Ok(w) = old_width_str.parse::<u32>() {
|
||||
|
||||
// Если ширина не найдена и путь начинается с "unsafe",
|
||||
// ищем ширину в формате "1440x"
|
||||
if width == 0 && path.starts_with("unsafe") {
|
||||
for part in path.split('/') {
|
||||
if part.ends_with('x') {
|
||||
if let Ok(w) = part.trim_end_matches('x').parse::<u32>() {
|
||||
width = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Если ширина не найдена в пути, проверяем имя файла
|
||||
if width == 0 {
|
||||
if let Some((name, width_str)) = base_filename.rsplit_once('_') {
|
||||
if let Ok(w) = width_str.parse::<u32>() {
|
||||
width = w;
|
||||
base_filename = name.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Очищаем base_filename от возможных префиксов пути
|
||||
if let Some(uuid) = base_filename.split('/').last() {
|
||||
base_filename = uuid.to_string();
|
||||
}
|
||||
|
||||
(base_filename, width, extension)
|
||||
(base_filename.to_string(), width, extension.to_string())
|
||||
}
|
||||
|
||||
/// Генерирует миниатюры изображения.
|
||||
|
@ -135,52 +108,74 @@ pub async fn thumbdata_save(
|
|||
content_type: String,
|
||||
) -> Result<(), actix_web::Error> {
|
||||
if content_type.starts_with("image") {
|
||||
warn!("original file name: {}", original_filename);
|
||||
warn!("[THUMB] Processing image: {}", original_filename);
|
||||
let (base_filename, _, extension) = parse_file_path(&original_filename);
|
||||
warn!("detected file extension: {}", extension);
|
||||
warn!("[THUMB] Parsed: base={}, ext={}", base_filename, extension);
|
||||
|
||||
let ext = extension.to_lowercase();
|
||||
let filename = format!("{}.{}", base_filename, ext);
|
||||
warn!("[THUMB] Normalized filename: {}", filename);
|
||||
|
||||
let img = match image::load_from_memory(&original_data) {
|
||||
Ok(img) => img,
|
||||
Ok(img) => {
|
||||
warn!("[THUMB] Successfully loaded image from memory, size: {}x{}",
|
||||
img.width(), img.height());
|
||||
img
|
||||
},
|
||||
Err(e) => {
|
||||
warn!("cannot load image from memory: {}", e);
|
||||
error!("[THUMB] Failed to load image from memory: {}", e);
|
||||
return Err(ErrorInternalServerError("cant load image"));
|
||||
}
|
||||
};
|
||||
|
||||
warn!("generate thumbnails for {}", filename);
|
||||
let format = match determine_image_format(&ext) {
|
||||
Ok(f) => {
|
||||
warn!("[THUMB] Using format: {:?}", f);
|
||||
f
|
||||
},
|
||||
Err(e) => {
|
||||
error!("[THUMB] Format error: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Определяем формат изображения
|
||||
let format = determine_image_format(&ext)?;
|
||||
|
||||
// Генерация миниатюр с использованием определённого формата
|
||||
match generate_thumbnails(&img, format).await {
|
||||
Ok(thumbnails_bytes) => {
|
||||
warn!("[THUMB] Generated {} thumbnails", thumbnails_bytes.len());
|
||||
|
||||
for (thumb_width, thumbnail) in thumbnails_bytes {
|
||||
let thumb_filename = format!("{}_{}.{}", base_filename, thumb_width, ext);
|
||||
// Загружаем миниатюру в S3
|
||||
if let Err(e) = upload_to_s3(
|
||||
warn!("[THUMB] Saving thumbnail: {}", thumb_filename);
|
||||
|
||||
match upload_to_s3(
|
||||
&state.storj_client,
|
||||
&state.bucket,
|
||||
&thumb_filename,
|
||||
thumbnail,
|
||||
thumbnail.clone(),
|
||||
&content_type,
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!("cannot load thumb {}: {}", thumb_filename, e);
|
||||
).await {
|
||||
Ok(_) => {
|
||||
warn!("[THUMB] Successfully saved thumbnail: {}", thumb_filename);
|
||||
// Сохраняем путь к миниатюре в Redis
|
||||
state.set_path(&thumb_filename, &thumb_filename).await;
|
||||
warn!("[THUMB] Cached path in Redis: {}", thumb_filename);
|
||||
},
|
||||
Err(e) => {
|
||||
error!("[THUMB] Failed to save thumbnail {}: {}", thumb_filename, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => {
|
||||
warn!("cannot generate thumbnails for {}: {}", filename, e);
|
||||
return Err(e);
|
||||
error!("[THUMB] Failed to generate thumbnails: {}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("[THUMB] Skipping non-image content type: {}", content_type);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Выбирает ближайший подходящий размер из предопределённых.
|
||||
|
|
Loading…
Reference in New Issue
Block a user