From 138024aefe3d9f9e55f3be29f6fb6c3c5adfba56 Mon Sep 17 00:00:00 2001 From: Will Miao Date: Sat, 13 Jun 2026 21:43:44 +0800 Subject: [PATCH] fix(preview): revert to FileResponse as default for all platforms (#975) The previous commit (a19ddc14) restored Linux sendfile but kept the manual streaming path for Windows via sys.platform guard. A Windows user reports performance is still worse than v1.0.5. Switch back to web.FileResponse for all files on all platforms as the default. The IOCP crash is an edge case (fast scrolling through many video previews) that affects few users, while the Python chunked I/O performance penalty affects everyone. _stream_file() is kept as an unused fallback for a future compat setting toggle. --- py/routes/handlers/preview_handlers.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/py/routes/handlers/preview_handlers.py b/py/routes/handlers/preview_handlers.py index e7de3aaa..3fb07808 100644 --- a/py/routes/handlers/preview_handlers.py +++ b/py/routes/handlers/preview_handlers.py @@ -4,7 +4,6 @@ from __future__ import annotations import logging import mimetypes -import sys import urllib.parse from pathlib import Path @@ -56,16 +55,11 @@ class PreviewHandler: logger.debug("Preview file not found at %s", str(resolved)) raise web.HTTPNotFound(text="Preview file not found") - # Video files on Windows: stream manually to avoid Windows IOCP native - # sendfile crash when the client disconnects mid-transfer (happens - # constantly when users scroll through a gallery of animated previews). - # On Linux/macOS, web.FileResponse uses kernel sendfile (zero-copy DMA) - # and does not have this issue, so it is safe and much faster. - suffix = resolved.suffix.lower() - if suffix in _VIDEO_EXTENSIONS and sys.platform == "win32": - return await self._stream_file(request, resolved) - - # aiohttp's FileResponse handles range requests and content headers for us. + # aiohttp's FileResponse handles range requests, content headers, and + # uses kernel sendfile (zero-copy DMA) on Linux/macOS. On Windows it + # uses IOCP-based _sendfile_native which can crash when the client + # disconnects mid-transfer during fast scrolling. The _stream_file() + # fallback is kept for a future compat toggle. return web.FileResponse(path=resolved, chunk_size=_CHUNK_SIZE) async def _stream_file(