From 159193ef439284cef79b11281b9653f571e871e6 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 25 Aug 2025 15:33:46 +0800 Subject: [PATCH] feat: Implement unique filename generation with conflict resolution using metadata hash --- py/services/civitai_client.py | 14 -------------- py/services/download_manager.py | 34 +++++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/py/services/civitai_client.py b/py/services/civitai_client.py index a390ef83..8767621e 100644 --- a/py/services/civitai_client.py +++ b/py/services/civitai_client.py @@ -193,20 +193,6 @@ class CivitaiClient: else: logger.error(f"Download failed for {url} with status {response.status}") return False, f"Download failed with status {response.status}" - - # Get filename from content-disposition header (only on first attempt) - if retry_count == 0: - content_disposition = response.headers.get('Content-Disposition') - parsed_filename = self._parse_content_disposition(content_disposition) - if parsed_filename: - filename = parsed_filename - # Update paths with correct filename - save_path = os.path.join(save_dir, filename) - new_part_path = save_path + '.part' - # Rename existing part file if filename changed - if part_path != new_part_path and os.path.exists(part_path): - os.rename(part_path, new_part_path) - part_path = new_part_path # Get total file size for progress calculation (if not set from Content-Range) if total_size == 0: diff --git a/py/services/download_manager.py b/py/services/download_manager.py index c89a9c90..8f491fa8 100644 --- a/py/services/download_manager.py +++ b/py/services/download_manager.py @@ -389,13 +389,39 @@ class DownloadManager: return formatted_path async def _execute_download(self, download_url: str, save_dir: str, - metadata, version_info: Dict, - relative_path: str, progress_callback=None, - model_type: str = "lora", download_id: str = None) -> Dict: + metadata, version_info: Dict, + relative_path: str, progress_callback=None, + model_type: str = "lora", download_id: str = None) -> Dict: """Execute the actual download process including preview images and model files""" try: civitai_client = await self._get_civitai_client() - save_path = metadata.file_path + + # Extract original filename details + original_filename = os.path.basename(metadata.file_path) + base_name, extension = os.path.splitext(original_filename) + + # Check for filename conflicts and generate unique filename if needed + # Use the hash from metadata for conflict resolution + def hash_provider(): + return metadata.sha256 + + unique_filename = metadata.generate_unique_filename( + save_dir, + base_name, + extension, + hash_provider=hash_provider + ) + + # Update paths if filename changed + if unique_filename != original_filename: + logger.info(f"Filename conflict detected. Changing '{original_filename}' to '{unique_filename}'") + save_path = os.path.join(save_dir, unique_filename) + # Update metadata with new file path and name + metadata.file_path = save_path.replace(os.sep, '/') + metadata.file_name = os.path.splitext(unique_filename)[0] + else: + save_path = metadata.file_path + part_path = save_path + '.part' metadata_path = os.path.splitext(save_path)[0] + '.metadata.json'