Immich Folder View 实用指南:以文件资源管理器方式浏览你的照片库
【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich
Folder View 是 Immich 在时间线(Timeline)之外提供的第二种浏览模式,它把一个文件资源管理器搬进了 Web 端:按文件夹逐级导航,逐层查看每个目录中的照片和视频资产。读完本文,你将掌握如何开启该功能、理解它依赖的originalPath数据链路,以及如何结合存储模板(Storage Template)把文件夹视图真正用起来。
什么是 Folder View
按官方文档 folder-view.md 的定义,Folder View 提供了一个与时间线并行的视图,形态上类似文件资源管理器,允许你在库(library)的文件夹与文件之间逐层导航。它最适合两类场景:
- 内容经过精心整理、目录结构规范的外部库(External Library);
- 配合一个配置得当的存储模板生成的清晰目录结构。
换句话说,时间线回答"按时间有什么",Folder View 回答"按目录结构有什么"。它的价值与资产落盘的目录组织程度直接挂钩——目录越规整,这个视图越好用。
开启 Folder View
在 Web 端进入Account Settings > Features > Folders即可启用。
从设置项的实现看(FeatureSettings.svelte/user-settings/FeatureSettings.svelte#L15-L16)),该功能实际保存了两个布尔配置,结构为folders: { enabled, sidebarWeb }:
enabled:总开关,决定是否启用文件夹视图能力;sidebarWeb:开启后,在 Web 端侧边栏的 Explorer 区域展示完整的文件夹树入口(仅在总开关打开后才可见)。
这两个值随用户偏好(preferences)持久化,登录后由authManager.preferences.folders读取。
实际使用:从侧边栏进入并逐层导航
启用后,即可从侧边栏进入 Folder View 页面。该页面对应前端路由 folders/+page.svelte/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte),页面由三部分构成:
- 左侧文件夹树:
Sidebar内的TreeItems组件渲染整棵文件夹树,当前目录以高亮图标标识; - 顶部面包屑:
Breadcrumbs组件基于当前树节点生成,可点击任意一级快速回跳; - 主内容区:
TreeItemThumbnails平铺当前目录下的子文件夹缩略图,其下方由GalleryViewer以画廊网格展示该目录下的资产(照片/视频)。
导航机制的核心是路径参数:点击一个子文件夹会调用joinPaths(data.tree.path, folderName)拼出新路径,再通过Route.folders({ path })跳转到同一页面的新路径(见 folders/+page.svelte/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte#L45-L55))。页面加载函数(folders/+page.ts/folders/[[photos=photos]]/[[assetId=id]]/+page.ts#L7-L31))的逻辑是:
foldersStore.fetchTree()拉取并构建完整文件夹树;- 读取 URL 中的
path查询参数,调用tree.traverse(path)定位到对应子树;若未带 path,则清空资产缓存以避免显示陈旧数据; - 仅当目标节点
hasAssets为真时,才调用fetchAssetsByPath请求该目录的资产列表——空目录不会发起无谓的资产请求。
此外,页面复用了时间线的多选能力:可对当前目录的资产批量执行共享、加相册、收藏、下载、改期、改位置、归档、设为隐藏、打标签、删除,以及触发重新生成缩略图、刷新元数据、转码视频等后台作业(见 folders/+page.svelte/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte#L119-L165))。
实现原理:两个 API 撑起整棵目录树
从源码结构看,Folder View 的全部数据来自两个服务端接口,定义在 view.controller.ts:
| 接口 | 作用 | 调用位置 |
|---|---|---|
getUniqueOriginalPaths | 返回当前用户名下所有资产的去重原始路径列表 | 前端构建目录树 |
getAssetsByOriginalPath | 按path查询参数返回某目录下的资产列表(AssetResponseDto[]) | 进入目录后加载资产 |
调用链为:控制器 → ViewService →ViewRepository,两个方法都只以userId为维度做数据隔离,即每个用户只能看到自己资产的目录结构。对应的单元测试见 view.service.spec.ts,其中验证了路径列表的透传与按originalPath前缀过滤资产的匹配逻辑。
前端:foldersStore 与 TreeNode
前端状态全部集中在 folders.svelte.ts:
fetchTree():调用getUniqueOriginalPaths()拿路径数组,交给TreeNode.fromPaths()构建树,再执行collapse()优化;只初始化一次(initialized标记),登出事件(AuthLogout)触发clearCache()重置;fetchAssetsByPath(path)/refreshAssetsByPath(path):以路径为键维护资产缓存,批量操作后通过refreshAssetsByPath强制刷新,保证目录内资产视图与操作结果一致。
树的构建与简化逻辑在 tree-utils.ts:
TreeNode.fromPaths(paths):把每条originalPath按分隔符逐段add进树,叶子节点标记hasAssets = true——这正好解释了页面为何只对hasAssets为真的节点发起资产请求;traverse(path):按路径分段逐级get定位子树,找不到时停留在最近的已知节点;collapse():若某节点只有一个子节点且自身无资产,就把父子两段合并成一个节点(例如把DCIM/与Camera/合并显示为DCIM/Camera),减少导航中的"单支路"噪音。
关键前提:originalPath 来自哪里
originalPath是资产实体上的"原始文件路径"字段(见 asset-response.dto.ts),它在资产导入/入库时由服务端生成,其目录结构正是由存储模板决定的。因此 Folder View 并不是在浏览服务器磁盘,而是基于数据库中记录的相对路径重建目录视图——这也是它只读、无文件系统写入操作的原因。若想让视图"好看",正确做法是先在管理后台配置存储模板,例如按YYYY/MM/等变量组织目录(可参考 storage-template.mdx),再让外部库或新导入资产落在该结构下。
适用边界小结
- 数据来源是
originalPath去重集合,目录树随资产增删变化,而非实时扫描磁盘; - 每个用户仅能看到自己资产的目录,接口按
userId隔离; - 该视图只做导航与批量操作入口,不能移动/重命名文件;组织目录的"源头"在存储模板与导入路径,而非此视图本身;
- 对目录结构松散、
originalPath冗长杂乱(如大量随机文件名目录)的库,建议先优化存储模板,Folder View 的可用性才会显著提升。
【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考