PicGo 内置了一个小型 HTTP 服务 PicGo-Server,很多编辑器插件、脚本和自动化工具都是通过它来上传图片的。不过它一直有个限制:图片只能传到当前的默认图床。比如你平时截图传 GitHub 的「Work」配置,写博客的图片想传到另一个「Blog」配置,就只能先去 PicGo 界面里切一下默认图床,传完再切回来。
从 v3.0.3 开始,这个限制没有了。你可以在请求里直接指定这一次上传用哪个已保存的图床配置。
先给结论,只要在 POST /upload 后面加上 query 参数就行:
# 把图片上传到 GitHub 图床下名为 "Work" 的配置
curl -X POST "http://127.0.0.1:36677/upload?uploader=github&configName=Work" \
-H "Content-Type: application/json" \
-d '{"list": ["/Users/molunerfinn/Desktop/photo.png"]}'
这次上传会用「Work」这个配置,你的默认图床不会被切换,也不会往配置文件里写任何东西。
准备工作
你需要:
- PicGo 3.0.3 或更高版本,可以在 下载页 拿到最新版。
- PicGo-Server 处于开启状态。它默认就是开着的,监听地址
127.0.0.1,端口36677。如果你改过,可以在「设置」里的「设置PicGo-Server」查看。 - 在 PicGo 里已经保存好了要用的图床配置,并且记得它的名字。
下文的例子都以默认地址 http://127.0.0.1:36677 为准。
三种上传方式都支持
PicGo-Server 的 /upload 接口本来就有三种用法,这次新增的参数对它们全部生效。
上传本地文件路径,请求体是 JSON,list 里放文件的绝对路径:
curl -X POST "http://127.0.0.1:36677/upload?uploader=github&configName=Work" \
-H "Content-Type: application/json" \
-d '{"list": ["/Users/molunerfinn/Desktop/a.png", "/Users/molunerfinn/Desktop/b.png"]}'
上传剪贴板里的图片,请求体留空即可:
curl -X POST "http://127.0.0.1:36677/upload?uploader=github&configName=Work"
用表单上传文件,字段名是 files,可以带多个文件。适合调用方和 PicGo 不在同一个文件系统里的情况,比如从容器或者另一个程序里直接把文件内容发过来:
curl -X POST "http://127.0.0.1:36677/upload?uploader=github&configName=Work" \
-F "files=@/Users/molunerfinn/Desktop/a.png" \
-F "files=@/Users/molunerfinn/Desktop/b.png"
三个参数怎么组合
一共三个参数:uploader 是图床的类型 ID,configName 是你保存配置时起的名字,configId 是配置的唯一 ID。它们都是可选的,按需组合:
| 参数 | 实际效果 |
|---|---|
| 不传 | 和以前一样,用当前的默认图床 |
uploader=github | 用 GitHub 图床当前选中的那个配置 |
uploader=github&configName=Work | 用 GitHub 图床下名为 Work 的配置 |
configName=Work | 在所有图床里找 Work,只能匹配到一个 |
configId=<id> | 按配置 ID 精确匹配 |
通常来说,uploader + configName 是最推荐的写法。同一个图床下的配置名不允许重复,所以这个组合一定能定位到唯一的配置,读起来也一目了然。另外配置名匹配时不区分大小写,configName=work 也能匹配到「Work」。
如果你的不同图床下有同名配置,比如 GitHub 和腾讯云 COS 下都有一个「Work」,只传 configName=Work 就会匹配到两个,PicGo 会直接返回错误,不会替你随便挑一个。这时候带上 uploader 就行。
uploader 填什么
内置图床的 ID 如下:
| 图床 | uploader |
|---|---|
| PicGo Cloud | picgo-cloud |
| GitHub | github |
| 阿里云 OSS | aliyun |
| 腾讯云 COS | tcyun |
| 七牛云 | qiniu |
| 又拍云 | upyun |
| SM.MS | smms |
| Imgur | imgur |
插件提供的图床,ID 由插件自己决定。有个偷懒的办法可以查:故意传一个不存在的 uploader,返回的错误信息里会列出所有可用的图床 ID。
curl -X POST "http://127.0.0.1:36677/upload?uploader=not-exist"
比如我本机装了 Cloudflare R2 的插件,返回的结果是这样的(我的 PicGo 界面是英文,所以提示也是英文):
{
"success": false,
"result": [],
"items": [],
"code": "UNKNOWN_UPLOADER",
"message": "Uploader \"not-exist\" is not registered. Available uploaders: [aliyun, tcyun, smms, github, qiniu, imgur, upyun, picgo-cloud, cloudflare-r2]."
}
最后的 cloudflare-r2 就是插件提供的图床 ID。这个请求在参数校验阶段就会被拒绝,不会真的上传任何东西,可以放心试。
什么时候用 configId
配置改名以后,原来的 configName 就对不上了。如果你的脚本要长期跑,不想因为改了个名字就失效,可以用 configId,它在配置改名后保持不变。
目前界面上不直接显示配置 ID,你可以在 PicGo 的配置文件 data.json 里找到它,位置在 uploader.<图床ID>.configList 下每个配置的 _id 字段。配置文件的路径:
- Windows:
%APPDATA%\picgo\data.json - macOS:
~/Library/Application Support/picgo/data.json - Linux:
$XDG_CONFIG_HOME/picgo/data.json或~/.config/picgo/data.json
另外,configId 和 configName 可以一起传。PicGo 会先按 ID 找,找不到再按名字找,适合既想用 ID 又想留一个兜底的场景。
返回结果和错误处理
上传成功时返回 HTTP 200,result 是图片链接数组,items 里有每张图片的详细信息:
{
"success": true,
"result": ["https://example.com/a.png"],
"items": [
{
"imgUrl": "https://example.com/a.png",
"fileName": "a.png",
"type": "github",
"width": 1280,
"height": 720
}
]
}
其中 type 是这次实际使用的图床,可以拿来确认图片确实去了你指定的地方。
参数有问题的时候,PicGo 会在上传之前就拒绝请求,返回 HTTP 400,不会悄悄回退到默认图床。这一点我觉得很重要:如果参数写错了还默默传到默认图床,图片就会出现在你没预料到的地方,而且很难发现。返回体里的 code 说明了具体原因:
| code | 含义 |
|---|---|
INVALID_UPLOAD_OPTION | 参数是空值,或者同一个参数传了多次 |
UNKNOWN_UPLOADER | uploader 对应的图床不存在 |
UPLOAD_CONFIG_NOT_FOUND | 找不到匹配的配置 |
UPLOAD_CONFIG_AMBIGUOUS | 匹配到了多个配置,需要补充 uploader 或改用 configId |
message 字段会给出更具体的说明,文案的语言跟随 PicGo 的界面语言。脚本里建议用 code 做判断,message 用来给人看。
配置名有中文或空格时要编码
配置名会出现在 URL 里,所以包含空格、中文等字符时,需要先做 URL 编码。比如配置名叫「工作 图床」:
# 「工作 图床」编码后是 %E5%B7%A5%E4%BD%9C%20%E5%9B%BE%E5%BA%8A
curl -X POST "http://127.0.0.1:36677/upload?uploader=github&configName=%E5%B7%A5%E4%BD%9C%20%E5%9B%BE%E5%BA%8A" \
-H "Content-Type: application/json" \
-d '{"list": ["/Users/molunerfinn/Desktop/photo.png"]}'
在代码里调用就省事多了,大部分语言的 URL 工具都会自动处理。比如 Node.js:
const url = new URL('http://127.0.0.1:36677/upload')
url.searchParams.set('uploader', 'github')
url.searchParams.set('configName', '工作 图床') // 会自动编码
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ list: ['/Users/molunerfinn/Desktop/photo.png'] })
})
const data = await res.json()
if (!data.success) {
console.error(data.code, data.message)
}
并发上传也没问题
不同的请求可以同时发给不同的配置,它们之间互不影响。比如一个脚本把博客配图传到「Blog」,同时另一个工具把截图传到「Work」,各自的进度和结果都不会串。
这也是以前「先切默认图床再上传」做不到的:切换默认图床是全局的,两个任务同时跑就会互相覆盖。现在每次请求自带配置,就不存在这个问题了。
最后
这个功能本身不复杂,不过对于用 PicGo 做自动化的同学来说,应该能省掉不少来回切换的麻烦。完整的 PicGo-Server 用法可以看 文档,这次版本的完整更新说明在 GitHub Release。
如果用的过程中遇到问题,欢迎到 issues 里反馈~