Files
video/util/file_util.py

85 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import datetime
from pathlib import Path
from typing import Dict
def save_face_to_up_images(
client_ip: str,
face_name: str,
image_bytes: bytes,
image_format: str = "jpg"
) -> Dict[str, str]:
"""
保存人脸图片到 `/up_images/用户IP/人脸名字/` 路径
确保db_path以up_images开头且统一使用正斜杠
参数:
client_ip: 客户端IP原始格式如192.168.1.101
face_name: 人脸名称(用户输入,可为空)
image_bytes: 人脸图片二进制数据
image_format: 图片格式默认jpg
返回:
字典success是否成功、db_path存数据库的相对路径、local_abs_path本地绝对路径、msg提示
"""
try:
# 1. 基础参数校验
if not client_ip.strip():
return {"success": False, "db_path": "", "local_abs_path": "", "msg": "客户端IP不能为空"}
if not image_bytes:
return {"success": False, "db_path": "", "local_abs_path": "", "msg": "图片二进制数据为空"}
if image_format.lower() not in ["jpg", "jpeg", "png"]:
return {"success": False, "db_path": "", "local_abs_path": "", "msg": "仅支持jpg/jpeg/png格式"}
# 2. 处理特殊字符(避免路径错误)
safe_ip = client_ip.strip().replace(".", "_") # IP中的.替换为_
safe_face_name = face_name.strip() if (face_name and face_name.strip()) else "未命名"
safe_face_name = "".join([c for c in safe_face_name if c not in r'\/:*?"<>|']) # 过滤非法字符
# 3. 构建根目录(强制转为绝对路径,避免相对路径混淆)
root_dir = Path("up_images").resolve() # 转为绝对路径如D:/Git/bin/video/up_images
if not root_dir.exists():
root_dir.mkdir(parents=True, exist_ok=True)
print(f"[FileUtil] 已创建up_images根目录{root_dir}")
# 4. 构建文件层级路径确保在root_dir子目录下
ip_dir = root_dir / safe_ip
face_name_dir = ip_dir / safe_face_name
face_name_dir.mkdir(parents=True, exist_ok=True) # 自动创建目录
print(f"[FileUtil] 图片存储目录:{face_name_dir}")
# 5. 生成唯一文件名(毫秒级时间戳)
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
image_filename = f"face_{safe_ip}_{timestamp}.{image_format.lower()}"
# 6. 计算路径确保所有路径都是绝对路径且在root_dir下
local_abs_path = face_name_dir / image_filename # 绝对路径
# 验证路径是否在root_dir下防止路径穿越攻击
if not local_abs_path.resolve().is_relative_to(root_dir.resolve()):
raise Exception(f"图片路径不在up_images根目录下安全校验失败{local_abs_path}")
# 数据库存储路径强制包含up_images前缀统一使用正斜杠
relative_path = local_abs_path.relative_to(root_dir.parent) # 相对于root_dir的父目录
db_path = str(relative_path).replace("\\", "/") # 此时会包含up_images部分
# 7. 写入图片文件
with open(local_abs_path, "wb") as f:
f.write(image_bytes)
print(f"[FileUtil] 图片保存成功:")
print(f" 数据库路径:{db_path}")
print(f" 本地绝对路径:{local_abs_path}")
return {
"success": True,
"db_path": db_path, # 格式为 up_images/192_168_110_31/小龙/xxx.jpg
"local_abs_path": str(local_abs_path), # 本地绝对路径(完整路径)
"msg": "图片保存成功"
}
except Exception as e:
error_msg = f"图片保存失败:{str(e)}"
print(f"[FileUtil] 错误:{error_msg}")
return {"success": False, "db_path": "", "local_abs_path": "", "msg": error_msg}