前言
自从博客从 WordPress 转到静态博客(先 Hexo 后 Jekyll)之后,文章的图片处理、图片上传就成了一个不大顺畅的事情。最先是使用了 vgy.me 提供的免费图床,支持直接从剪切板上传,操作上相对比较简单,也不需要任何本地存储。不过后来 vgy.me 进行了升级改版,原先的剪切板上传功能也不再支持了,偶尔还出现图片像素被降低、丢失的问题。同时,考虑到 WebP 格式可能会适合博客使用,而 vgy.me 还不支持该格式。于是开始切换到 “对象存储 CDN” 的方案。本地准备好的 PNG 格式图片,先通过 cwebp 命令行转成 WebP 格式图片,再通过 uPic 工具修改文件名后上传到对象存储。由于此前采用的是腾讯云的 COS 对象存储和 CDN,经常面临着 SSL 证书更新等琐碎的事情。这样一来,整体的效率实际上并不高,只能说勉强接受。
现有工具及存储考察
为此,也对其他工具和对象存储进行了考察。
PicGo 是一款集客户端 UI 和命令行于一体的图片上传工具,虽然可以利用命令串联的方式简单将图片格式转换和上传两步变成一步,但还是有那么点不舒服的地方,比如 PicGo 不提供文件名修改(为固定长度随机字符串)的特性。而 uPic 本身关注于客户端桌面交互,不提供命令行接口。
至于对象存储,国内各家云服务厂商提供的都需要自行手动更新 SSL 证书,且收费。尽管腾讯云 CDN 目前老用户可以每月领券免费使用,但一旦忘记就开始被收费了。实际上也有逐步转向收费的趋势。国外各家云服务厂商基本上都需要收费使用对象存储或者 CDN,大差不差。
当然,网上一直有一种 “Backblaze B2 Cloudflare” 的解决方案。由于 B2 本身存储和读写操作都有免费额度,流量需要收费,且无法自定义域名,而 B2 和 Cloudflare 同属于宽带联盟(内部流量免费),Cloudflare 还提供 URL 重写功能,这种解决方案一时成为了潮流。不过,B2 的访问链接是中间带着一串参数,重写之后仍然还是有部分参数,最终的 URL 并不是那么朴素。总的来说,还是有那么点别扭。
R2 的出现
因此观望了许久,直到 Cloudflare 推出了 R2。R2 是一款对标 AWS S3 的产品,基于 Cloudflare 对宽带联盟的承诺而构建,为存储对象提供零成本出口,实际上就是免费 CDN。由于 Cloudflare 本身就是一家 CDN 服务商,自定义对象存储访问域名、自动生成部署 SSL 证书这些事情就变得轻而易举了。R2 提供 10GB 的免费存储,读操作每月免费 1000 万次,写、更新和删除操作每月免费 100 万次。这对于一般的静态博客来说,应该完全足够了,即使超出了免费额度,超出部分收费也相较其他云服务厂商便宜一些。
对笔者而言,R2 产品将对象存储和 CDN 两款产品有机地结合起来,解决了静态博客图片对外访问前的“最后一公里”。于是想从 COS 迁移到 R2,无奈 uPic 这个时候卖了个“破绽”。uPic 似乎在开始转向商业收费,Github 上不再发布新版本,而仅在 Appstore 上继续更新对 R2 的支持。当然,Appstore 上的 uPic 是收费的(4.99 美元,其实也不贵)。
小提示
R2 虽然说是对标 AWS S3,但是并没有完整实现所有 API 接口,所以目前 Github 上发布的 uPic 版本无法兼容。尽管可以自行通过修改 uPic 的开源代码来实现兼容,但毕竟修改别人的代码的成本还是有一点高的。
开个新项目
在充分梳理个人使用需求之后,还是决定开个新项目——开发一款简单易用的命令行工具 PICTL(全称 Picture Control)。该工具须具备以下特性:
- 考虑图片的存储空间大小和网页加载时长,所有图片应被压缩并转成 WebP 格式;
- 所有图片的名称应被修改成一个固定长度随机字符串,并支持上传到类 S3 的对象存储;
- 简单易用,命令行优先,无网页或桌面交互界面;
- (可选)自动添加水印;
- (可选)根据设定自动调整图片尺寸;
- (可选)可以直接从剪切板读取图片。
架构设计
根据所列出的特性,这款命令行工具主要的模块就是:图片处理模块和上传模块,架构如下图所示。
图片处理模块包括图片压缩、图片格式转换、图片水印、尺寸调整等功能,可以进行无缝横向扩展。上传模块主要包括对于三种存储方式的支持:第一类是最为广泛的类 S3 对象存储,如 R2、AWS S3 及国内外云服务厂商各种对象存储等,第二类是目前仍然在博客中广泛流行的第三方图床,如 SM.MS、vgy.me、chevereto 类型图床等,第三类是自托管 Git 平台和 FTP 平台。
特此声明
鉴于 Github、Gitlab、Gitee 等公共代码托管平台均禁止把 Git 仓库作为图床的做法,本工具仅支持自建 Git 平台,如自建 Gitlab 和 Gitlab Pages。如试图上传到公共代码托管平台,本工具会自行中断上传。
本工具由于仅支持命令行,所以计划用 Python 和 Click 进行开发。虽然借助 Google Fire 也可以快速开发命令行工具,但其使用方式上与原生 *nix 的命令行工具有所不同。相比之下,用 Click 开发可能会麻烦一点,但能够开发出更类原生的 Python 命令行工具。当然,目前开发上还是比较喜欢使用 Rust 或者 Go 语言来开发高性能的命令行工具。不过,本工具只是做一些非常简单的工作,没有性能上的瓶颈,用 Python 开发也足够了。
开发计划
请移步 Github Project 了解更多。
使用方法
目前,PICTL 已经在 Github 和 PyPI 同步发布了 v0.1.0 版本。该版本实现了以上架构图中的基本功能,即特性中的前三点必要项。接下来介绍一下如何安装和使用本工具。
安装
目前支持两种安装方式:源码安装和 PIP 安装,后续将增加对于 brew 的支持。
小提示
安装前,请务必确保已满足 Python 版本高于 3.10 的条件。
源码安装
代码语言:javascript复制git clone https://github.com/zhonger/pictl
cd pictl
pip3 install .
PIP 安装
代码语言:javascript复制pip3 install pictl
使用
显示版本
代码语言:javascript复制╰─$ pictl -V
PICTL 0.1.0
列举所有支持命令
目前 v0.1.0 版本包含四个子命令:config(配置管理),compress(图片处理),upload(上传文件)和 cup(一键式压缩、转换、上传)。
代码语言:javascript复制╰─$ pictl
Usage: pictl [OPTIONS] COMMAND [ARGS]...
A command line tool for image processing and uploading (ex. S3-type).
Now it supports:
- transformation from other image types to `webp` image as well as
image compression.
- image file uploading to AWS S3 or Cloudflare R2.
Options:
-V, --version Show the pictl version.
-h, --help Show this message and exit.
Commands:
compress Compress any image into `webp` image.
config Operations for the config file `~/.pictlrc`.
cup Compress image and upload to remote storage (compress and...
upload Upload the file to remote storage
config 子命令
config 子命令包含 add(添加配置)、delete(删除配置)、info(查看所有配置)和 init(初始化配置)四种操作。使用本工具需要先执行初始行配置操作,再执行其他配置操作。
代码语言:javascript复制╰─$ pictl config
Usage: pictl config [OPTIONS] COMMAND [ARGS]...
Operations for the config file `~/.pictlrc`.
Options:
-h, --help Show this message and exit.
Commands:
add Add configs to the config file.
delete Delete config group from the config file.
info Check the configs.
init Initialize config file with default configs.
如下所示,使用 pictl config init
命令初始化配置。第二次执行时,由于已存在配置文件,会提示已经初始化过了。
╰─$ pictl config init
The settings has been initilized in /home/ubuntu/.pictlrc.
╰─$ pictl config init
/home/ubuntu/.pictlrc already exists.
Please add settings or change it manaully.
使用 pictl config info
以 JSON 格式打印所有配置信息。配置文件默认采用 TOML 格式。
╰─$ pictl config info
{
'basic': {'length': 6, 'ntype': 'random', 'algorithm': 'sha1'},
}
╰─$ cat ~/.pictlrc
[basic]
length = 6
ntype = "random"
algorithm = "sha1"
使用 pictl config add
以命令行交互方式添加配置(以下是 R2 的例子)。添加完成后可以再次查看新增后的所有配置。
╰─$ pictl config add
****** Please input these information ******
Group Name (default 'blog'): test
[?] Type: : R2
S3
> R2
Account ID: testid
Bucket Name: test
Key: testkey
Secret: testsecret
Prefix (Default is None):
Access Url (like `https://i.example.com`): https://i.example.com
New group 'test' has been saved in /Users/zhonger/.pictlrc.
╰─$ pictl config info
{
'basic': {'length': 6, 'ntype': 'random', 'algorithm': 'sha1'},
'test': {
'endpoint': 'https://testid.r2.cloudflarestorage.com/test',
'bucket': 'test',
'prefix': '',
'key': 'testkey',
'secret': 'testsecret',
'url': 'https://i.example.com',
'type': 'R2'
}
}
使用 pictl config delete
命令可以选择删除远程配置组(此处为了展示,除 test 外还添加了其他配置组)。
╰─$ pictl config delete
[?] Please select one group: : test
blog
cover
> test
test has been deleted.
compress 子命令
本子命令输入参数为图片文件名,可以带路径。输出图片会被保存在命令执行位置,而非原图片所在目录。执行该操作后,图片还不会被上传,需要继续使用 upload 命令完成上传。
代码语言:javascript复制╰─$ pictl compress -h
Usage: pictl compress [OPTIONS] FILENAME
Compress any image into `webp` image.
FILENAME is the name of the file to compress.
Options:
-h, --help Show this message and exit.
╰─$ pictl compress ../../pictl/fig01.png
The output file is EVyP2J.webp
upload 子命令
如下所示,使用 pictl upload
命令加上指定上传文件名和远程配置组即可完成上传。
╰─$ pictl upload -h
Usage: pictl upload [OPTIONS] FILENAME GROUP
Upload the file to remote storage.
FILENAME is the name of the file to upload.
GROUP is the group in the config file you want to use.
Options:
-h, --help Show this message and exit.
╰─$ pictl upload EVyP2J.webp test
Direct URL: https://i.example.com/EVyP2J.webp
Markdown: ![EVyP2J.webp](https://i.example.com/EVyP2J.webp)
HTML Code: <img src="https://i.example.com/EVyP2J.webp" alt="EVyP2J.webp" />
cup 子命令
cup 子命令 = compress 子命令 upload 子命令,仅需要指定初始图片文件和远程配置组,即可一步完成图片压缩、格式转换、修改名称、上传。
代码语言:javascript复制╰─$ pictl cup -h
Usage: pictl cup [OPTIONS] FILENAME GROUP
Compress image and upload to remote storage (compress and upload).
FILENAME is the name of the file to compress.
GROUP is the group in the config file you want to use.
Options:
-h, --help Show this message and exit.
╰─$ pictl cup ../../pictl/fig01.png test
The output file is Gl8qhI.webp
Direct URL: https://i.example.com/Gl8qhI.webp
Markdown: ![Gl8qhI.webp](https://i.example.com/Gl8qhI.webp)
HTML Code: <img src="https://i.example.com/Gl8qhI.webp" alt="Gl8qhI.webp" />
TODO
目前的 v0.1.0 版本还比较简陋,不过已经能满足笔者的必要需求,有效提升效率。后续将继续完善、新增功能:
- 自动补全(shell completion),增强命令行使用体验。
- 增加对各云服务厂商提供对象存储的支持。
- 增加对各流行图床的支持。
- 增加对自托管 Git 的支持。
- 增加对 FTP 的支持。
- 增加包括水印、调整大小等在内的图片处理的支持。
- 增加与 Unplash 等公共图库的连接,更加便于博客封面的操作。
参考资料
- 隆重推出 Cloudflare R2 Storage —— 快速、可靠的对象存储,减免出口费用
- R2 文档
版权声明: 如无特别声明,本文版权归 仲儿的自留地 所有,转载请注明本文链接。
代码语言:txt复制 (采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) 许可协议进行授权)
本文标题:《 图片处理及上传命令行工具 —— PICTL 》
本文链接:https://cloud.tencent.com/developer/article/2296750