fix: 代码审查修复 + 精简重写 README
后端修复: - 白板删除踢人失效:delete_whiteboard 改 async def,删除后直接 await hub.close_board()。原实现用 asyncio.get_running_loop() 在同步 REST handler (threadpool)里调用必抛 RuntimeError 被 except 吞掉,close_board 从不执行。 同时移除 service 的 hub 依赖(close_board 改由 controller 调用,service 只管 DB)。 - delete_file 去重复查询:原先 get_out_with_disk_path + get_by_id 查两次, 合并为一次;磁盘 unlink 失败加 logger.warning(原静默吞掉致磁盘泄漏无记录)。 - get_hub 单例加 threading.Lock 双重检查(防 REST threadpool 与 WS 事件循环 并发首访各建一个 hub)。 - file_controller 公开 /api/files list 加 Query(ge=1, le=10000) 约束(原无上限可 DoS)。 前端修复: - applyRemoteUpdate 有未发送编辑时重发:合并远端更新后若本地有 pending 编辑 (editor.value !== lastSentText)重新 scheduleSend,避免被 lastSentText 短路丢弃。 - init 不覆盖未发送编辑:断线重连后若本地有未发送内容,作为新版本发上去而非被 init 覆盖。 - applyRemoteUpdate 仅在编辑器已有焦点时恢复焦点,避免抢按钮焦点。 - api() 401 时 location.reload() 触发浏览器 Basic Auth 弹窗(原只 toast 卡死)。 README: - 精简重写,补全 Ubuntu 从 0 安装、Apache 反代(含 WS)、配置项表格、防火墙说明。
This commit is contained in:
@@ -8,6 +8,7 @@ upload_root),不再有 HTTP 登记接口。
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from collections.abc import Iterator
|
||||
@@ -21,6 +22,8 @@ from ..dao.uploaded_file_dao import UploadedFileDAO
|
||||
from ..models.uploaded_file import UploadedFile
|
||||
from ..schemas.file import FileUploadResponse, UploadedFileOut
|
||||
|
||||
logger = logging.getLogger("zikai.upload")
|
||||
|
||||
|
||||
def hash_stream(chunks: Iterator[bytes]) -> tuple[int, str]:
|
||||
"""对一段字节块序列流式计算 (size, sha256)。供多条上传路径复用。"""
|
||||
@@ -95,18 +98,17 @@ class UploadService:
|
||||
def delete_file(self, file_id: int) -> bool:
|
||||
"""硬删除:删磁盘文件 + 删 DB 行。磁盘缺失不阻断 DB 清理。返回是否命中。
|
||||
|
||||
供单删/批删复用,保证删除语义一致。
|
||||
供单删/批删复用,保证删除语义一致。磁盘删除失败仅记日志,仍清 DB 行
|
||||
(保证列表不再显示),避免磁盘文件泄漏却无任何记录。
|
||||
"""
|
||||
_, path = self.get_out_with_disk_path(file_id)
|
||||
row = self.dao.get_by_id(file_id)
|
||||
if row is None:
|
||||
out, path = self.get_out_with_disk_path(file_id)
|
||||
if out is None:
|
||||
return False
|
||||
if path is not None:
|
||||
try:
|
||||
Path(path).unlink(missing_ok=True)
|
||||
except Exception:
|
||||
# 即使磁盘删除失败也继续清 DB 行,保证列表不再显示
|
||||
pass
|
||||
except Exception as exc:
|
||||
logger.warning("删除磁盘文件失败 file_id=%s path=%s: %s", file_id, path, exc)
|
||||
self.dao.delete(file_id)
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user