市面上的图床要么纯存储没展示,要么相册好看但不能外链。我想要两者兼得——于是自己写了一个。
缘起:图床和相册为什么不能是一个东西?
用过不少图床服务,最后都遇到了同一个尴尬:
- 纯图床(各种 S3 直链服务):上传快、外链稳,但给别人看图时只能甩一坨裸链接,没有相册、没有排版、没有地图轨迹。
- 相册站(各种开源相册程序):展示效果漂亮,瀑布流、EXIF 面板、标签搜索一应俱全——但拿外链?要么没有这个功能,要么链接长得像乱码。
我想要的东西其实很简单:
- 当图床用:上传后一键复制 Markdown / HTML / 纯 URL / BBCode 外链,贴到博客、论坛直接显示。
- 当相册用:访客打开网站能看到排版精美的相册,支持标签、搜索、图片详情、EXIF 信息。
- 再加点料:实况照片(Live Photo)能动起来,带 GPS 的照片在 3D 地球上标出足迹。
听起来不难,但找了一圈——真没有同时满足这三条的现成方案。
那就自己写。LandCloud 就这么来了。
它能做什么
一句话概括:个人图床 + 相册展示网站,对外展示,对内管理,外链、分享、地图一把梭。
核心能力一览
| 能力 | 说明 |
|---|---|
| 图片外链 | 直链(CDN)+ 代理链接(站内 /f/ 路由),Markdown/HTML/URL/BBCode 四种格式一键复制 |
| 相册展示 | 公开 / 私密 / 密码三种可见性;瀑布流网格、响应式分页、浏览量统计 |
| 图片处理 | sharp 自动生成缩略图 + WebP 压缩 + EXIF 提取(相机、镜头、光圈、快门、ISO、GPS) |
| 实况照片 | 支持 Apple / Google / Samsung / 小米 / OPPO / vivo 的 Live Photo,前端自动识别并播放 |
| HEIC 转换 | iPhone 拍的 HEIC/HEIF 格式自动转 JPEG,变体照常生成 |
| 3D 地图足迹 | Cesium 3D 地球,带 GPS 的照片聚合打点,缩放展开缩略图,点击跳详情 |
| 手机扫码上传 | 后台生成二维码,手机扫码免登录上传(HMAC 临时令牌,10 分钟有效) |
| 密码分享 | 自定义密码 + 有效期(永久/1天/7天/30天),bcrypt 哈希存储,错误限频 |
| 标签搜索 | 全站关键词搜索(标题/文件名/描述/标签/年份),标签聚合页 |
| 主题切换 | 暗色/亮色模式,HeroUI v3 组件体系 |
| SEO | sitemap + robots.txt,私密内容禁止收录 |
上传流程:直传 S3,服务器不扛流量
很多图床的瓶颈在于:图片先过服务器再转存到存储——带宽和内存全浪费在搬运上。
LandCloud 用的是 S3 预签名直传方案:
浏览器请求预签名 URL(校验管理员)
│
▼
浏览器直传 S3 ←─── 流量不过服务器
│
▼
浏览器回调 /api/upload/complete
│
▼
服务端校验对象 → 写记录(pending) → 异步处理
│
▼
sharp 生成变体 + EXIF 提取 → done
上传时流量直接走 浏览器 → S3,服务器只负责签发预签名 URL 和处理回调。处理流水线(缩略图、WebP、EXIF)异步执行,失败可一键重试。
支持 Cloudflare R2 / AWS S3 / MinIO 等任何 S3 协议存储,换服务商只需要改环境变量。
实况照片:让图床也能"动"起来
这是我最得意的功能。
市面上的图床几乎没有支持 Live Photo 的——你上传一张实况照片,它就变成一张死图。但实况照片的本质是「静态图 + 短视频」,明明可以保留动态部分。
LandCloud 实现了一套纯原生的多厂商 Live Photo 解析器:
| 厂商 | 解析方式 |
|---|---|
| Apple | 双文件模式(HEIC + MOV) |
| XMP 元数据解析 | |
| Samsung | XMP 元数据解析 |
| 小米 | XMP 元数据解析 |
| OPPO | XMP 元数据解析 |
| vivo | XMP 元数据解析 |
| 通用兜底 | ftyp marker 扫描 |
上传后自动提取静态帧和关联视频,前端展示时带实况照片徽章,点击播放短视频。HEIC 格式还会自动转 JPEG 生成变体——iPhone 用户终于不用先手动转格式了。
3D 地图足迹:你的照片会说话
拍照片带 GPS 坐标的人越来越多,但大多数相册程序对 GPS 数据的利用止步于「在地图上标个点」。
LandCloud 集成了 Cesium 3D 地球:
- 所有含 GPS 的公开照片自动聚合打点
- 缩放级别变化时聚合数量动态调整
- 点击聚合点展开该位置的缩略图列表
- 点击缩略图跳转到图片详情页
- 侧边统计卡片展示足迹覆盖范围
Cesium 采用路由级按需加载,首页 bundle 不含地图代码——不会拖慢首屏性能。
手机扫码上传:随拍随传
电脑上写博客,手机上拍了张照片想立刻用?不用数据线,不用传到中间服务再下载。
后台点一下「手机上传」,弹出二维码。手机扫码进入上传页(HMAC 临时令牌,10 分钟有效),直接选照片上传到同一个 S3 桶。回到电脑刷新后台,图已经在列表里了。
安全:该锁的都锁了
图床项目最大的风险不是性能,是数据安全。LandCloud 在这方面下了功夫:
| 措施 | 说明 |
|---|---|
| Supabase RLS | 所有数据库表默认拒绝,仅管理员 JWT 可写,访客仅读公开数据 |
| 密码分享 | bcrypt 哈希存储,错误尝试限频(同 IP 5 次/分钟) |
| 预签名 URL | 10 分钟过期,限定 key 前缀与文件大小 |
| 代理路由 | 私密图片一律返回 404(不暴露存在性) |
| MIME 校验 | 服务端回调时校验 MIME 白名单 + 魔数,拒绝可执行文件伪装 |
| service_role 隔离 | 服务端密钥仅限 Route Handler 内部使用,绝不下发到客户端 |
技术栈
| 层 | 选型 | 为什么选 |
|---|---|---|
| 框架 | Next.js 16+(App Router, Turbopack) | 前后端一体化,Route Handlers + Server Actions |
| UI | HeroUI v3 + Tailwind CSS v4 | 组件库成熟,暗色模式原生支持 |
| 数据/认证 | Supabase(Postgres + Auth + RLS) | 免费额度够用,RLS 开箱即用 |
| 对象存储 | 通用 S3 协议(R2 / S3 / MinIO) | 协议标准,供应商可随时切换 |
| 图片处理 | sharp | Node 生态最快的图片处理库,缩略图/WebP/EXIF 一把梭 |
| 地图 | Cesium 3D 地球 | 3D 可视化天花板,路由级按需加载 |
| 测试 | Vitest(43 项单测)+ Playwright(6 条 E2E) | 关键路径全覆盖 |
| 部署 | Vercel | Next.js 原生支持,零配置部署 |
选型原则和 RadCloud 一样:站在巨人的肩膀上,把精力花在体验打磨上。
部署:5 分钟拥有自己的图床
# 1. Clone 仓库
git clone https://github.com/wyml/LandCloud.git
cd LandCloud
# 2. 安装依赖(自动拷贝 Cesium 静态资源)
npm install
# 3. 配置环境变量
cp .env.example .env.local
# 填入 Supabase URL/Key、S3 凭证、管理员邮箱
# 4. 跑起来
npm run dev
部署到 Vercel 的步骤:
- 推送仓库并连接 Vercel 项目
- 在项目设置中逐项填入环境变量
- 首次部署后在 Supabase 执行
supabase/migrations/全部脚本 - 冒烟测试:前台首页 → 后台登录 → 上传一张图 → 确认公开页出现 → 私密图直链返回 404
详细的环境变量说明和备份恢复指引都在 README 里。
项目状态
目前 M0~M8 全部完成并提交,M9(测试加固与上线)为收尾里程碑,包含 43 项单元测试和 6 条 Playwright E2E 关键路径。核心功能已全部可用,生产环境部署冒烟通过。
项目完全开源,仓库地址:github.com/wyml/LandCloud
写在最后
从 CATIA 建模到无人机飞控,从医学影像平台到图床相册——看起来跨度很大,但底层逻辑一直没变:遇到不顺手的工具,就自己造一个。
市面上的图床要么没有展示能力,相册要么没有外链能力。LandCloud 把两者揉到一起,还塞进了实况照片和 3D 地球。如果你也想要一个「既是图床又是相册」的个人图片站,欢迎来用、来提意见、来一起参与。
仓库地址:github.com/wyml/LandCloud
有问题或想法,欢迎 Issue 和 PR。
#LandCloud #图床 #相册 #Next.js #Supabase #开源 #Cesium