# Avatar Storage Research > 研究日期: 2026-07-11 > 目标: 找到 username → 头像文件路径的完整映射规则 ## 核心发现 头像文件路径与 username 的映射基于 **MD5(username)**,不是 UUID 或数据库字段。 ## 路径规则 ``` {data_root}/avatar/{hash[0:2]}/{hash[2:4]}/user_hd_{full_hash}.png ``` 示例: | username | MD5 (前8位) | 路径 | |----------|------------|------| | `wxid_51ap3m6p9xs722` | `28ef8e12...` | `avatar/28/ef/user_hd_28ef8e129c...png` | | `filehelper` | `9e20f478...` | `avatar/9e/20/user_hd_9e20f47889...png` | ## 文件命名优先级 1. `user_hd_{hash}.png` — 高清头像(优先) 2. `user_{hash}.png` — 普通头像(回退) 3. 也可尝试 `{hash[0:2]}/{hash[2:4]}/{hash}/user_hd_{hash}.png`(有些版本嵌套 hash 子目录) ## 验证结果 | Username | Hash (前8位) | 文件存在 | 大小 (估算) | |----------|-------------|---------|------------| | `wxid_51ap3m6p9xs722` | `28ef8e12` | ✅ YES | ~3KB | | `filehelper` | `9e20f478` | ❌ NO | N/A | ## 其他尝试的方法 1. **hdheadimginfo 表**: WeChat DB 中该表存在但 sqlite3 在 root shell 中不可用,未能直接查询。MD5 方法已验证足够。 2. **rcontact 扩展字段**: rcontact 表无直接头像路径字段。头像通过文件系统 + MD5 映射。 3. **ImgFlag / WxFileIndex**: 未发现头像相关的 filename→username 映射表。 ## 实现方案 ```python import hashlib def _resolve_avatar_path(username: str) -> str | None: """username → MD5 → avatar hash directory path""" h = hashlib.md5(username.encode()).hexdigest() base = f"{data_root}/avatar/{h[:2]}/{h[2:4]}" for fname in [f"user_hd_{h}.png", f"user_{h}.png"]: path = f"{base}/{fname}" if os.path.exists(path): return path return None ``` ## 已知限制 - **无 small_ 缩略图**: 实际测试未发现 `small_` 前缀的缩略图。返回原图,前端用 CSS 缩放。 - **无 username→hash 缓存表**: 每次请求都需计算 MD5 + 检查文件系统。可在后续版本增加 LRU 缓存。 - **文件系统权限**: 头像文件在 WeChat 数据目录下,需要 `su` 权限读取。当前实现:`su -c cp` 到 `/tmp` 后 `send_file`。