From 3207a67dcb33dd845cffe806a4ef4493e1917cee Mon Sep 17 00:00:00 2001 From: suguanYang Date: Mon, 7 Sep 2026 10:30:43 +0800 Subject: [PATCH] fix(worker): normalize encoded document filenames --- .../document_ingestion/creation_service.py | 4 ++-- .../unit/test_document_ingestion_filename.py | 18 ++++++++++++++++++ .../support/internal_parse_name.py | 2 ++ .../tests/unit/test_internal_parse_name.py | 12 ++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 apps/api/tests/unit/test_document_ingestion_filename.py diff --git a/apps/api/app/services/document_ingestion/creation_service.py b/apps/api/app/services/document_ingestion/creation_service.py index 597aac796..ec88c65ce 100644 --- a/apps/api/app/services/document_ingestion/creation_service.py +++ b/apps/api/app/services/document_ingestion/creation_service.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from datetime import datetime, timezone from typing import cast -from urllib.parse import urlparse +from urllib.parse import unquote, urlparse from app.repositories.job_repository import JobRepository from app.services.document_ingestion.command import DocumentIngestionCommand @@ -308,7 +308,7 @@ def _build_job_response( def _resolve_url_source_file_name(*, source_url: str, file_extension: str) -> str: parsed_url = urlparse(source_url) - url_basename = str(os.path.basename(parsed_url.path)) + url_basename = unquote(str(os.path.basename(parsed_url.path))) if url_basename and os.path.splitext(url_basename)[1].lower() == file_extension: return url_basename if url_basename: diff --git a/apps/api/tests/unit/test_document_ingestion_filename.py b/apps/api/tests/unit/test_document_ingestion_filename.py new file mode 100644 index 000000000..703e455de --- /dev/null +++ b/apps/api/tests/unit/test_document_ingestion_filename.py @@ -0,0 +1,18 @@ +from app.services.document_ingestion.creation_service import ( + _resolve_url_source_file_name, +) + + +def test_resolve_url_source_file_name_decodes_percent_encoded_path() -> None: + source_url = ( + "https://files.example.test/" + "%E4%B8%AD%E6%96%87%E7%AE%80%E5%8E%86-%E9%9B%B7%E7%BF%94-" + "%E4%B8%AD%E7%A7%91%E9%99%A2%285%29.doc" + ) + + source_file_name = _resolve_url_source_file_name( + source_url=source_url, + file_extension=".doc", + ) + + assert source_file_name == "中文简历-雷翔-中科院(5).doc" diff --git a/apps/worker/app/services/document_parser/support/internal_parse_name.py b/apps/worker/app/services/document_parser/support/internal_parse_name.py index 7a59ed8c7..f4ecee2db 100644 --- a/apps/worker/app/services/document_parser/support/internal_parse_name.py +++ b/apps/worker/app/services/document_parser/support/internal_parse_name.py @@ -3,6 +3,7 @@ import os from dataclasses import dataclass +from urllib.parse import unquote from app.services.common.file_utils import path_handle from app.services.document_parser.support.filename_limits import ( @@ -27,6 +28,7 @@ def normalize_internal_parse_name( candidate_name = ( os.path.basename(filename) if isinstance(filename, str) and filename else "" ) + candidate_name = unquote(candidate_name) cleaned_name = ( path_handle(candidate_name, mode="clean_single") if candidate_name else "" ) diff --git a/apps/worker/tests/unit/test_internal_parse_name.py b/apps/worker/tests/unit/test_internal_parse_name.py index c43dcabb4..cabcb912d 100644 --- a/apps/worker/tests/unit/test_internal_parse_name.py +++ b/apps/worker/tests/unit/test_internal_parse_name.py @@ -4,10 +4,22 @@ from pathlib import Path from app.services.document_parser.support.internal_parse_name import ( + normalize_internal_parse_name, prepare_internal_parse_input, ) +def test_normalize_internal_parse_name_decodes_url_encoded_filename() -> None: + encoded_filename = ( + "%E4%B8%AD%E6%96%87%E7%AE%80%E5%8E%86-%E9%9B%B7%E7%BF%94-" + "%E4%B8%AD%E7%A7%91%E9%99%A2%285%29.doc" + ) + + normalized_name = normalize_internal_parse_name(encoded_filename) + + assert normalized_name == "中文简历-雷翔-中科院-5-.doc" + + def test_prepare_internal_parse_input_handles_long_encoded_filename( tmp_path, ) -> None: