Files
FileHost/server/utils/image-public-path.ts
T
Yeomai 89ea2fb25d
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
feat: 新增视频床与文件床,视频支持 HLS 转码
文件床
- 新增 files/ 存储前缀与 media_type 索引列,图片、视频、文件三类资源独立
- 新增文件上传、列表、删除、批量删除接口,禁止 html/htm/svg
- 支持公开直链与 Token 访问两种模式,后台可切换,直链强制附件下载

视频床
- 新增 videos/ 存储前缀与视频上传接口,单文件上限 500MB
- 接入 ffmpeg 转码队列,并发数与单任务核心数可配,默认串行
- 五档转码质量:直接封装 / 速度 / 平衡 / 质量 / 压缩(压缩档可调码率比例)
- 码率控制避免转码后体积反超源文件,音频跟随源音轨不放大不压缩
- 转码进度实时上报,成功后删除源文件,失败时保留源文件与可用链接
- 上传时自动抽帧生成封面,视频与封面各有独立链接
- 删除视频时中断转码并清理切片、封面与源文件

媒体库
- 图库、视频库、文件库三套独立统计,含趋势、占用与来源分布
- 统一筛选、多选、批量删除、批量标签、网格/列表切换,显示方式按类型分别记忆
- 视频详情对齐图片详情,视频库支持在线播放(hls.js,兼容回退原文件)

修复
- 清理无主的切片、封面与开发期遗留的 ffmpeg 进程
- 源文件按设计删除后,索引不再被启动孤儿清理误删
- 视频统计口径与列表一致,转码中的视频不计入统计
- 转码失败时回收已写入的部分切片,避免残留
- 设置页停用检查更新(与上游版本号已不对应)

其他
- Docker 镜像安装 ffmpeg
- git remote 指向内网仓库
2026-10-17 03:14:57 +08:00

45 lines
1.5 KiB
TypeScript
Raw Permalink 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 { basename } from 'node:path'
import { DEFAULT_FOLDER, validateFileKey, validateImageKey } from './image-key'
/** 存储 key → 对外 URL 路径(不含域名) */
export function storageKeyToPublicPath(key: string): string {
const prefix = `${DEFAULT_FOLDER}/`
if (key.startsWith(prefix)) return key.slice(prefix.length)
return key
}
/**
* 对外 URL 路径:
* - hideFolder=true:仅文件名(img.com/a8K3xP.webp)
* - hideFolder=false:去掉内部 images/ 前缀(img.com/2026/08/a.webp)
*/
export function toPublicImagePath(key: string, hideFolder: boolean): string {
if (hideFolder) return basename(key)
return storageKeyToPublicPath(key)
}
/** 公开相对路径 → 存储 key;legacy 完整 key(含 images/)仍接受 */
export function toStorageKeyFromPublicPath(publicPath: string): string | null {
const raw = publicPath.replace(/^\/+/, '')
if (!raw) return null
if (validateImageKey(raw)) return raw
// 文件床直链保留 files/ 前缀,避免与图片路径混用
if (validateFileKey(raw)) return raw
const candidate = `${DEFAULT_FOLDER}/${raw}`
return validateImageKey(candidate) ? candidate : null
}
const HIDDEN_DATE_PATH_PATTERN
= /^\d{4}\/\d{2}\/[^/\\]+\.(jpg|jpeg|png|webp|gif|svg|ico)$/i
const BARE_FILENAME_PATTERN
= /^[^/\\]+\.(jpg|jpeg|png|webp|gif|svg|ico)$/i
export function isHiddenImageDatePath(path: string): boolean {
return HIDDEN_DATE_PATH_PATTERN.test(path)
}
export function isBareImageFilename(path: string): boolean {
return BARE_FILENAME_PATTERN.test(path)
}