config.yaml 新增 path_mapping 段声明宿主机前缀与容器挂载点前缀的对应关系。 用户在 Web 界面和 config 里填宿主机真实路径(如群晖 /volume2/...), 程序在真正落盘、调用云盘 SDK 前透明转成容器内路径,保证文件写到 bind mount 而不是容器 overlay 文件系统;前端显示/返回的路径再反向转回宿主机形式。 无映射配置时所有 to_container/to_host 均原样返回,向后兼容老配置。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""宿主机路径 ↔ 容器路径映射
|
||||
|
||||
用于让用户在 Web 界面和 config.yaml 里填宿主机真实路径(如群晖的 /volume2/...),
|
||||
程序在真正写盘/调用云盘 SDK 之前再转换成容器内挂载点路径(如 /app/downloads)。
|
||||
保证文件落到 bind mount 卷而不是容器 overlay 文件系统。
|
||||
|
||||
匹配规则:最长前缀匹配,以路径分隔符为边界。无匹配则原样返回,不阻断流程。
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
|
||||
logger = logging.getLogger("media_downloader")
|
||||
|
||||
# (host_prefix, container_prefix) 列表,加载时按 host_prefix 长度倒序
|
||||
_mappings: list = []
|
||||
|
||||
|
||||
def _normalize(p: str) -> str:
|
||||
"""去掉尾部 /,统一用 / 做分隔符"""
|
||||
if not p:
|
||||
return ""
|
||||
return p.replace("\\", "/").rstrip("/")
|
||||
|
||||
|
||||
def load_mappings(items: list):
|
||||
"""从 config 里的 path_mapping 列表加载映射
|
||||
|
||||
items 每项形如 {'host': '/volume2/save/tgdowload', 'container': '/app/downloads'}
|
||||
"""
|
||||
global _mappings
|
||||
pairs = []
|
||||
for it in items or []:
|
||||
h = _normalize(str(it.get("host", "") or ""))
|
||||
c = _normalize(str(it.get("container", "") or ""))
|
||||
if not h or not c:
|
||||
continue
|
||||
pairs.append((h, c))
|
||||
# 按 host 前缀长度倒序,保证最长前缀优先命中
|
||||
pairs.sort(key=lambda x: len(x[0]), reverse=True)
|
||||
_mappings = pairs
|
||||
if _mappings:
|
||||
logger.info("path_mapper loaded %d mapping(s): %s", len(_mappings), _mappings)
|
||||
|
||||
|
||||
def _match_prefix(p: str, prefix: str) -> bool:
|
||||
"""前缀匹配,必须落在路径分隔符边界上,避免 /a/b 匹配到 /a/bc"""
|
||||
return p == prefix or p.startswith(prefix + "/")
|
||||
|
||||
|
||||
def to_container(p: str) -> str:
|
||||
"""宿主机路径 → 容器路径。无匹配原样返回。"""
|
||||
if not p:
|
||||
return p
|
||||
norm = _normalize(p)
|
||||
for host, container in _mappings:
|
||||
if _match_prefix(norm, host):
|
||||
return container + norm[len(host):]
|
||||
return p
|
||||
|
||||
|
||||
def to_host(p: str) -> str:
|
||||
"""容器路径 → 宿主机路径。无匹配原样返回。"""
|
||||
if not p:
|
||||
return p
|
||||
norm = _normalize(p)
|
||||
for host, container in _mappings:
|
||||
if _match_prefix(norm, container):
|
||||
return host + norm[len(container):]
|
||||
return p
|
||||
Reference in New Issue
Block a user