2026-05-03-23-22-10 修复阅览切换和下载触发

This commit is contained in:
2026-05-03 23:26:36 +08:00
parent bff7eead08
commit 7b7c555321
6 changed files with 304 additions and 10 deletions

View File

@@ -41,6 +41,9 @@ PORT = 8787
JOBS = {}
JOBS_LOCK = threading.Lock()
DICOM_FILE_CACHE = {}
DICOM_VOLUME_CACHE = {}
DICOM_VOLUME_CACHE_LOCK = threading.Lock()
DICOM_VOLUME_CACHE_LIMIT = 2
LIBRARY_DIR = APP_DIR / "web_library"
LIBRARY_META = LIBRARY_DIR / "library.json"
RESULT_DIR = APP_DIR / "web_results"
@@ -178,6 +181,56 @@ def sorted_dicom_files(dicom_dir):
return sorted_files
def dicom_dir_signature(dicom_dir):
dicom_dir = Path(dicom_dir).resolve()
files = list(dicom_dir.glob("*.dcm"))
return (
str(dicom_dir),
len(files),
max((file_path.stat().st_mtime for file_path in files), default=0),
)
def load_cached_dicom_volume(dicom_dir):
dicom_dir = Path(dicom_dir).resolve()
signature = dicom_dir_signature(dicom_dir)
cache_key = str(dicom_dir)
with DICOM_VOLUME_CACHE_LOCK:
cached = DICOM_VOLUME_CACHE.get(cache_key)
if cached and cached["signature"] == signature:
cached["last_access"] = time.time()
return cached["volume"]
volume = load_dicom_volume(dicom_dir)
DICOM_VOLUME_CACHE[cache_key] = {
"signature": signature,
"volume": volume,
"last_access": time.time(),
}
while len(DICOM_VOLUME_CACHE) > DICOM_VOLUME_CACHE_LIMIT:
oldest_key = min(
DICOM_VOLUME_CACHE,
key=lambda key: DICOM_VOLUME_CACHE[key].get("last_access", 0),
)
if oldest_key == cache_key:
break
DICOM_VOLUME_CACHE.pop(oldest_key, None)
return volume
def clear_dicom_caches(dicom_dir=None):
if dicom_dir is None:
DICOM_FILE_CACHE.clear()
with DICOM_VOLUME_CACHE_LOCK:
DICOM_VOLUME_CACHE.clear()
return
cache_key = str(Path(dicom_dir).resolve())
DICOM_FILE_CACHE.pop(cache_key, None)
with DICOM_VOLUME_CACHE_LOCK:
DICOM_VOLUME_CACHE.pop(cache_key, None)
def find_library_item(item_id):
return next((item for item in list_library() if item["id"] == item_id), None)
@@ -227,7 +280,7 @@ def make_library_reformat_preview(item_id, plane, index, window):
plane = plane if plane in {"coronal", "sagittal"} else "coronal"
window = window if window in VIEWER_WINDOWS else "default"
volume = load_dicom_volume(item["dicomPath"])
volume = load_cached_dicom_volume(item["dicomPath"])
def normalize_reformat_index(raw_index, count):
if str(raw_index) == "middle":
@@ -1156,7 +1209,7 @@ class Handler(BaseHTTPRequestHandler):
write_library_meta(remaining)
upload_root = Path(target["dicomPath"]).resolve().parent
if upload_root.exists() and upload_root.is_relative_to(LIBRARY_DIR.resolve()):
DICOM_FILE_CACHE.pop(str(Path(target["dicomPath"]).resolve()), None)
clear_dicom_caches(target["dicomPath"])
shutil.rmtree(upload_root)
preview_cache = PREVIEW_CACHE_DIR / item_id
if preview_cache.exists():
@@ -1188,8 +1241,11 @@ class Handler(BaseHTTPRequestHandler):
self.send_header("Content-Disposition", f'attachment; filename="{file_path.name}"')
self.send_header("Content-Length", str(file_path.stat().st_size))
self.end_headers()
with file_path.open("rb") as file_handle:
shutil.copyfileobj(file_handle, self.wfile)
try:
with file_path.open("rb") as file_handle:
shutil.copyfileobj(file_handle, self.wfile)
except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError):
return
def send_cors_headers(self):
self.send_header("Access-Control-Allow-Origin", "*")