4 minutes
用 iOS Shortcuts 直接从手机上传照片到图床
之前在《Hugo 操作纪要》里提到过,本站的图片是通过 GitHub + PicGo + jsdelivr 搭的图床。这个方案本身很稳定,但流程对手机很不友好:拍完照要先传到电脑,再打开 PicGo 上传,再复制链接粘贴回 Markdown。很多时候光是"手机传电脑"这一步就有足够fiction了。
这篇记录一下怎么用 iOS Shortcuts 把这个流程压缩成"分享照片 → 剪贴板自动拿到链接",全程不用电脑,也不用换图床服务——底层还是原来的 GitHub 仓库,只是把 PicGo 换成了手机自动化。
为什么不用 Google Photos 链接
第一反应可能是"直接用 Google Photos 分享链接不就行了"。试过之后发现行不通:Google Photos 的分享链接指向一个网页而不是图片文件本身,没法直接当 <img src> 用;网页上"复制图片地址"能拿到一个 googleusercontent.com 的直链,但 Google 不保证这个链接长期有效,随时可能失效或被限流,不适合用在博客里长期引用。iCloud 共享相册链接也是同样的问题。
方案:iOS Shortcuts + GitHub Contents API
思路很简单:在 Photos 的分享菜单里加一个 Shortcut,选中照片直接调用 GitHub 的 Contents API,把照片以 base64 形式 PUT 到 moonlt-site/storage-host 仓库,再把返回的 path 拼成 jsdelivr 链接,扔进剪贴板。
第一步:建一个权限最小的 GitHub Token
在 github 账号下生成一个 Fine-grained personal access token:
- Repository access: Only select repositories →
storage-host - Permissions → Contents: Read and write(这一步最容易漏,Metadata 是必选的只读项,但真正决定能不能写文件的是 Contents,不是 Actions)
第二步:搭建 Shortcut
新建一个 Shortcut,打开 Share Sheet(类型选 Images),然后依次添加下面这些 action(名称保留英文,方便对照 Shortcuts App 里的实际名字), 注意替换 **部分**:
Repeat with Each (Shortcut Input)
Convert Image → JPEG (input 显式设为 Repeat Item)
Base64 Encode (Line Breaks 设为 None)
Current Date
Format Date → Custom: yyyyMMdd-HHmmss
Random Number (1000–9999)
Text: <FormattedDate>-<RandomNumber>.jpg
Get Contents of URL
URL: https://api.github.com/repos/**GITHUB ACCOUNT NAME**/**REPO NAME**/contents/img/<Text>
Method: PUT
Headers:
Authorization: Bearer <**TOKEN**>
Accept: application/vnd.github+json
Request Body (JSON):
message: "add moment photo"
content: <Base64 Encoded>
Get Dictionary Value (key: content) in [Contents of URL]
Get Dictionary Value (key: path) in [Dictionary Value]
Text: https://cdn.jsdelivr.net/gh/**GITHUB ACCOUNT NAME**/**REPO NAME**-host@main/<Dictionary Value>
Add to Variable: AllLinks
End Repeat
Combine Text (AllLinks, New Line)
Copy to Clipboard
Show Notification
分享一张或多张照片给这个 Shortcut,几秒后剪贴板里就是一行或多行现成的图片链接,直接粘贴进Markdown文件即可。
踩过的坑
这个 Shortcut 看起来没几步,实际调试花了不少时间,记录几个印象最深的错误,方便以后自己(或者别人)少走弯路:
403 Resource not accessible by personal access token:token 的 Permissions 里勾选了 Actions 而不是 Contents。GitHub 的 fine-grained token 权限分得很细,Actions管的是 workflow,跟建文件完全无关。422 path cannot end with a slash:如果把subfolder/xxx.jpg整个塞进一个变量,再插入 URL 输入框——变量里带的这个forward slash/会被 Shortcuts 处理成别的东西,导致 GitHub 收到的路径最后变成空的(相当于以/结尾)。解决办法是把目录名subfolder/直接打在 URL 里的字面文本部分(或者去掉subfolder),变量里只放不含斜杠的文件名。- 上传成功但
"size":0:文件建出来了,但是空文件。原因是Convert Image这个 action 的输入框一直显示灰色的占位文字 “Image”,没有被显式绑定到Repeat Item——不会主动报错,只是悄悄地什么都不转换。 content is not valid Base64:Base64 Encode默认的 Line Breaks 是 “Every 76 Characters”,会按 MIME 格式每 76 字符插入一个换行。GitHub 的 API 不接受带换行的 base64,需要手动把 Line Breaks 改成 None。
单独看每一条都不复杂,但当初是从"can’t parse response"这种笼统的报错开始一层层剥出来的,中间还顺手发现 Shortcuts 的 “Receive input from Share Sheet” 其实不是一个可以搜索添加的 action,而是藏在 Shortcut Details 里的一个开关。
多设备同步 & 安全提示
如果想在 iPad 上也用这个 Shortcut,在两台设备的 设置 → [你的名字] → iCloud → Shortcuts 里都打开同步开关即可自动出现,不需要手动导出。
需要提醒的是:token 是明文写死在 Authorization Header 里的,只在自己登录同一 Apple ID 的设备间用 iCloud 同步是安全的,但如果通过 iCloud 链接或 AirDrop 把这个 Shortcut 分享给别人,对方会拿到一份对仓库有写权限的 token——如果要发布或分享 shortcut 前要记得这一点。