环境:Python3.11.9 stabled

IDE:Pycharm2023.3.1.1 Typora 1.9.5

成品:upload.exe

项目背景

之前本地博文是用Typora + Picgo + COS,对于上传到Minio,需要安装额外的插件,也不支持对图片的转换。目前所有附件和图片都迁移至自建的Minio中,COS并不承担任何业务数据的存储,只保留备份的数据。为了满足本地博文图片上传的需要,用 Python 编写一个上传图片到 Minio 的脚本,并将其打包成exe文件。这个过程不仅适用于图片上传功能,也可以应用到其他 Python 脚本的打包需求中。

脚本编写

安装库

  • Minio SDK 用于与 Minio 服务进行交互。

  • Pillow 用于处理和转换图片格式。

  • aiohttp 用于处理异步请求,支持从 URL 获取图片。

  • requests 用于 HTTP 请求。

pip install minio pillow aiohttp requests

这些都是必须要安装的,开发过程中其他库可以选用更轻量的库来减小打包后的体积。

查看文档

地址:Typora自定义脚本上传图片文档

根据文档,最重要的是Typora会传入${filename}或者${filepath},可以一次性上传多张图片,脚本要返回值要用url以换行进行切分,且url必须是干净的,不能有其他输出。

配置约定

  1. 定义Minio的配置如下:

host = "xxxx.xxxx.com"
port = "xxxx"
access_key = "xxxxxxxxxxxxxxxxxxxx"
secret_key = "xxxxxxxxxxxxxxxxxxxx"
bucket_name = "xxxxxx"

这样拼出来的endpoint就是endpoint = f"{host}:{port}",保留host没有直接用host:port主要是后面我们要返回url给typora

  1. 定义上传路径为host/bucket/files/${year}/${month}/

  2. 定义文件名规则是 日期+6位随机UUIDcurrentDate-uuid4[6].webp

给定脚本

这段脚本提供了一些基本的功能:

  1. 异常处理,且不进行错误重试

    • 减小代码冗余,上传不成功就不处理了。

  2. 异步并发上传

    • 使用 asyncioaiohttp 进行异步操作,通过限制最大并发数(使用 Semaphore)来控制上传任务的数量,避免一次性上传过多图片导致系统资源消耗过大。

  3. 图片格式转换

    • 使用Pillow 将图片转换为 WebP 格式,个人需要,也比较建议将PNG和JPEG的图片进行处理。WebP相较于前两种,压缩率更高,可以减少存储空间。

程序打包

  1. 选用pyinstaller打包,本来源码就不大,因此用UPX简单压缩优化下就可以了。

    pip install pyinstaller
    
  2. UPX下载地址:UPX下载地址

  3. 执行打包

    pyinstaller --onefile --icon=icon.ico --noconsole upload.py
    

    image-20250117154526444

  4. 执行打包(upx压缩)

    pyinstaller --onefile --icon=icon.ico --noconsole --upx-dir="D:\envs\to\upx-4.2.4-win64" upload.py
    

image-20250117160021043

对比发现优化了9.2%,体积小于15M问题不大,不需要过分优化了。压缩前的的体积也不是很大,建议用压缩前的,UPX压缩后可能会导致Win报毒。

脚本使用

  1. 偏好设置上传图片,指定脚本

  2. 验证图片,可以看到我们打印的结果符合官网自定义的结果

image-20250117164303163

扩展

给定几个以下扩展(利用AI实现起来简单)

  1. 多存储策略

  2. GUI页面开发

  3. 水印功能

总结

很多配置都是写死了,有需要可以针对源码对原有功能二开,对于已经打包的exe文件就可以扩展到其他项目的打包和分发。