v1.0.7, fix Identical filenames caused settings to overwrite each other

This commit is contained in:
2026-09-19 03:09:26 +03:00
parent 6312d813a7
commit 1015949c15

View File

@ -22,7 +22,7 @@ use tracing::info;
async fn get_version() -> impl IntoResponse { async fn get_version() -> impl IntoResponse {
Json(serde_json::json!({ Json(serde_json::json!({
"version": "1.0.6", "version": "1.0.7",
"timestamp": chrono::Utc::now().timestamp() "timestamp": chrono::Utc::now().timestamp()
})) }))
} }
@ -192,17 +192,19 @@ async fn create_print(
) -> Result<Json<JobView>, (StatusCode, String)> { ) -> Result<Json<JobView>, (StatusCode, String)> {
info!("📥 Получен запрос на печать"); info!("📥 Получен запрос на печать");
let mut settings_map: HashMap<String, PrintSettings> = HashMap::new(); let mut settings_list: Vec<Option<PrintSettings>> = Vec::new();
let mut files_data: Vec<(String, bytes::Bytes)> = Vec::new(); let mut files_data: Vec<(String, bytes::Bytes)> = Vec::new();
while let Some(field) = multipart.next_field().await.unwrap_or(None) { while let Some(field) = multipart.next_field().await.unwrap_or(None) {
let field_name = field.name().unwrap_or("").to_string(); let field_name = field.name().unwrap_or("").to_string();
if field_name == "settings" { if field_name == "settings" {
if let Ok(text) = field.text().await { let parsed = match field.text().await {
if let Ok(s) = serde_json::from_str::<PrintSettings>(&text) { Ok(text) => serde_json::from_str::<PrintSettings>(&text).ok(),
settings_map.insert(s.filename.clone(), s); Err(_) => None,
} };
} // Пушим даже при ошибке парсинга (None), чтобы индексы не съезжали
settings_list.push(parsed);
} else if field_name == "files" { } else if field_name == "files" {
let file_name = field.file_name().unwrap_or("unknown").to_string(); let file_name = field.file_name().unwrap_or("unknown").to_string();
if let Ok(data) = field.bytes().await { if let Ok(data) = field.bytes().await {
@ -216,21 +218,26 @@ async fn create_print(
} }
let mut job_files: Vec<JobFile> = Vec::new(); let mut job_files: Vec<JobFile> = Vec::new();
for (file_name, data) in files_data {
for (i, (file_name, data)) in files_data.into_iter().enumerate() {
let ext = Path::new(&file_name) let ext = Path::new(&file_name)
.extension() .extension()
.and_then(|e| e.to_str()) .and_then(|e| e.to_str())
.unwrap_or("") .unwrap_or("")
.to_lowercase(); .to_lowercase();
let temp = if ext.is_empty() { let temp = if ext.is_empty() {
NamedTempFile::new() NamedTempFile::new()
} else { } else {
NamedTempFile::with_suffix(&format!(".{}", ext)) NamedTempFile::with_suffix(&format!(".{}", ext))
}; };
if let Ok(temp) = temp { if let Ok(temp) = temp {
let path = temp.into_temp_path(); let path = temp.into_temp_path();
if fs::write(&*path, &data).await.is_ok() { if fs::write(&*path, &data).await.is_ok() {
let settings = settings_map.get(&file_name).cloned(); // i-й файл ↔ i-й набор настроек — имена могут совпадать
let settings = settings_list.get(i).cloned().flatten();
job_files.push(JobFile { job_files.push(JobFile {
name: file_name, name: file_name,
path, path,
@ -258,6 +265,7 @@ async fn create_print(
let view = job.view(); let view = job.view();
store.lock().unwrap().insert(job_id.clone(), job); store.lock().unwrap().insert(job_id.clone(), job);
Ok(Json(view)) Ok(Json(view))
} }
@ -526,27 +534,18 @@ fn run_lp(path: &Path, settings: Option<&PrintSettings>, duplex_pass: Option<&st
} }
} }
// ──────────────────────────────────────────────────────────
// СЛОТЫ:
// • Первый проход дуплекса (odd) → Upper
// • Второй проход дуплекса (even) → Lower (ручная подача)
// • Обычная печать (не дуплекс) → Upper
// ──────────────────────────────────────────────────────────
match duplex_pass { match duplex_pass {
Some("odd") => { Some("odd") => {
// ПЕРВЫЙ проход — обычный лоток
cmd.arg("-o").arg("InputSlot=Upper"); cmd.arg("-o").arg("InputSlot=Upper");
cmd.arg("-o").arg("page-set=odd"); cmd.arg("-o").arg("page-set=odd"); // Нечётные страницы
} }
Some("even") => { Some("even") => {
// ВТОРОЙ проход — ручная подача
cmd.arg("-o").arg("InputSlot=Lower"); cmd.arg("-o").arg("InputSlot=Lower");
cmd.arg("-o").arg("page-set=even"); cmd.arg("-o").arg("page-set=even"); // Чётные страницы
cmd.arg("-o").arg("outputorder=reverse"); cmd.arg("-o").arg("outputorder=reverse");
cmd.arg("-o").arg("orientation-requested=6"); cmd.arg("-o").arg("orientation-requested=6");
} }
_ => { _ => {
// Обычная односторонняя печать
cmd.arg("-o").arg("InputSlot=Upper"); cmd.arg("-o").arg("InputSlot=Upper");
} }
} }