2026-05-03-23-22-10 修复阅览切换和下载触发
This commit is contained in:
@@ -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", "*")
|
||||
|
||||
Reference in New Issue
Block a user