个人图床工具开发

博客第一篇:我用 Vibe Coding 给自己写了个图床
这是这个博客的第一篇文章。按照惯例,第一篇应该写”为什么开博客”。 但我决定写点更实在的:这个博客的配图,存在哪里? 答案是——我自己写的一个图床。这篇文章里所有配图,都由它供养。
为什么是图床
开博客第一件事不是选主题、不是写自我介绍,而是解决一个基础设施问题:图片放哪。
我盘了一圈常见方案:
| 方案 | 问题 |
|---|---|
| 免费图床 | 指不定哪天跑路,图片变红叉,历史文章全废 |
| GitHub 仓库当图床 | 国内访问速度感人,仓库越背越重 |
| 微博 / 公众号图床 | 防盗链一开,外链全挂 |
| 云厂商对象存储 | 一个月几块钱,换来”自己说了算” |
结论很清晰:用阿里云 OSS 自建一个。自己的图片、自己的桶,谁也拿不走。
而且我还有个私心:这个博客本身就是我练手 Vibe Coding 的试验场。第一篇博文就写”这个博客的图床是怎么来的”,顺便完成一次自举——完美闭环。
我的 Vibe Coding 姿势:先立规矩,再谈写码
我对 Vibe Coding 的理解是:AI 负责写码,我负责当产品经理、架构评审和安全审计。
完全放养是不行的,尤其这个项目碰云密钥、碰对象存储权限,出事就是真金白银。所以开工前我先做了三件事:
- 写了一份”项目宪法”(仓库里的
AGENTS.md)。里面全是红线:长期密钥只许待在 Netlify 环境变量里、前端只许用 15 分钟有效的临时凭证、临时凭证只给上传权限不给删除权限、不许动与任务无关的代码…… - 把需求拆成任务清单,一次只推进一个任务,走完质量门禁才算完。
- 涉及密钥、权限、部署的变更,AI 必须先交方案、我点头后才动手。
规矩立得越狠,后面越省心。这是整个项目最重要的一个决定。
架构:一个没有服务器的”服务端”
最终长这样:
浏览器 ──① 请求上传授权──▶ Netlify Function ──② 用长期密钥换临时凭证──▶ 阿里云 STS ▲ │ └──────────────③ 返回临时凭证(15 分钟有效,仅允许上传)◀───────────────┘ │ └──④ 携带临时凭证,浏览器直传图片──▶ 阿里云 OSS(公共读) │ ◀──────────────⑤ 拿到图片 URL,复制 Markdown / HTML─────────────────────┘关键点:图片不经过服务器。
Netlify Function 唯一的职责是”发签证”——验证环境配置、向阿里云 STS 申请一张限定权限的临时凭证,然后交给浏览器。浏览器拿着签证自己把图片直传 OSS。服务器不过手文件,自然就没有流量成本、没有并发瓶颈、没有存储压力。
这套架构一分钱服务器都不用买:Netlify 免费额度托管前端和函数,OSS 按量付费,个人图床一个月几块钱。
安全:钥匙要管好
图床工具最重要的不是功能,是别把云账号钥匙弄丢了。这个项目的安全设计有四层:
- 长期 AccessKey 只存在于 Netlify 环境变量,不进代码、不进仓库、不进前端构建产物,连报错信息里都不允许出现变量的值(只有变量名)。
- 前端只持有临时凭证,有效期 15 分钟,过期自动重新申请。
- 最小权限:临时凭证只允许往
uploads/前缀下执行”上传”这一个动作,没有删除权限、没有列目录权限。就算凭证泄漏,攻击者能做的也仅仅是往一个前缀里塞文件。 - Bucket 公共读、写关闭:图片 URL 可以直接访问(这是图床的本职),但匿名用户写不进任何东西。
过程:契约先行 + 质量门禁
开发按 6 个任务推进,其中两个做法我觉得值得复制到所有项目:
契约先行。 服务端授权接口先写契约文档和 mock 实现,前端先对接 mock 把”选图 → 授权 → 上传 → 复制链接”整条链路跑通,最后才把 mock 换成真的阿里云 STS。换实现那天,前端代码一行没改——接口是稳定的,实现是可替换的。
质量门禁。 每次改动必须跑过 npm run validate 四道门:TypeScript 类型检查、ESLint、44 个单元测试、生产构建。AI 每次想偷懒跳过测试的时候,门禁都会把它拦下来。
踩坑实录(全文最有营养的部分)
开发和联调一共踩了四个坑,每个都很典型:
坑 1:本地好好的,一上 Netlify 就 500。 阿里云 Tea SDK 的 CommonJS 产物没有 __esModule 标记,Netlify 的 esbuild 打包后,default import 拿到的是 exports 对象而不是构造函数。本地运行完全正常,部署上去直接炸。最后写了一个 resolveStsClientCtor 同时兼容两种模块形态。 经验:本地通过 ≠ 生产通过,打包器会改变模块解析行为。
坑 2:Windows 不让我监听 5173 端口。 npm run dev 直接 EACCES。查了一圈才知道,Windows 的 Hyper-V/WSL 会动态保留 5141–5240 这一整段端口,应用根本抢不到。换个端口区间立刻就好(可用 netsh interface ipv4 show excludedportrange protocol=tcp 查看保留段)。 经验:开发环境起不来,先怀疑操作系统。
坑 3:EntityNotExist.Role——角色明明存在。 STS 报角色不存在,但 RAM 控制台里角色明明躺着。最后是 Netlify 环境变量里粘贴的角色 ARN 串了行。 经验:报”不存在”的错,先怀疑自己抄的配置值,而不是怀疑云厂商。
坑 4:上传永远返回 -1,什么错误信息都没有。 STS 链路全通、凭证到手,但 PUT 就是上不去,状态码 -1,服务端日志里”无事发生”。这是请求被浏览器拦截的典型特征。根因:OSS Bucket 的 CORS 规则没加 Netlify 站点的域名。 经验:静默失败的跨域请求,优先查 CORS,再怀疑代码。
四个坑,没有一个是代码逻辑问题——全是环境、配置、平台行为。这大概也是真实世界开发的常态。
收获
- Vibe Coding 的上限,取决于你立的规矩。
AGENTS.md写得越狠,产出越稳。 - “契约 + mock”是把大任务切小的最好手段,前后端可以各跑各的,最后无缝合拢。
- 所有诡异的 bug 最后都有平凡的根因:配置抄错、端口被占、跨域没配。
后续计划
- 上传历史记录(localStorage)
- 剪贴板粘贴上传
此文是由AI直接生成
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!




