前言
最近作者决定使用Halo CMS搭建自己的博客,但是Halo商城中的几个MarkDown编辑器就写作体验上相比Typora来说还是相差甚远。个人认为目前最佳的MarkDown写作方式还是 Typora + 图片上传器 + 图床,编写之后导入到Halo中,这种方式兼顾了写作体验和文章的可迁移性。在Halo CMS 中,用户上传的文件会保存在 /upload/
目录下,因此我们无需额外搭建图床,只需实现一个图片上传器即可。
实现思路
根据Typora官方文档,如果我们设置了自定义的图像上传器,那么当我们在使用粘贴的方式插入图片时,Typora会自动给图像生成器传递图片路径,类似这样:
python uploader.py 图片路径1 图片路径2
图片生成器只需完成上传逻辑,并且在控制台输出这样的内容:
Upload Success:
http://remote-image-1.png
http://remote-image-2.png
之后 Typora 就会从输出中获取远程图片 url,并替换 Markdown 文档中使用的原始本地图片。
那么uploader.py
的实现思路就很简单了:
- 抓包分析上传图片的请求和参数。
- 使用Python 的
requests
库来模拟这个文件上传操作。 - 输出图片的远程链接。
使用教程
安装Python环境
作者使用的版本是Python 3.13.3,已有Python环境可忽略。
复制代码并且保存
可以命名为uploader.py
,保存的路径最好不要有中文。
import requests
from datetime import datetime
import os
import sys
# 全局变量
URL = '你的博客地址'
COOKIE = '你的Cookie'
GROUP_NAME = '分组名称'
def upload(file_path, custom_filename):
"""上传图片文件并返回上传成功后的URL"""
upload_api = f'{URL}/apis/api.console.halo.run/v1alpha1/attachments/upload' # 上传API的URL
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0', # 用户代理
'Accept': '*/*', # 接受所有类型的响应
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', # 接受的语言
'Accept-Encoding': 'gzip, deflate, br', # 接受的编码
'Referer': f'{URL}/console/attachments', # 请求来源
'Origin': URL, # 请求的来源域名
'Sec-Fetch-Dest': 'empty', # 安全获取目标
'Sec-Fetch-Mode': 'cors', # 安全获取模式
'Sec-Fetch-Site': 'same-origin', # 安全获取站点
'Priority': 'u=0', # 优先级
'Te': 'trailers', # 尾部
'Connection': 'keep-alive', # 保持连接
'Cookie': COOKIE # Cookie用于身份验证
}
data = {
'policyName': 'default-policy', # 上传策略名称
'groupName': GROUP_NAME # 上传分组名称
}
files = {
'file': (custom_filename, open(file_path, 'rb'), 'image/png') # 上传文件,指定自定义文件名
}
response = requests.post(upload_api, headers=headers, data=data, files=files) # 发送POST请求
if response.status_code == 200: # 如果响应状态码为200,表示上传成功
return f'{URL}/upload/{custom_filename}' # 返回上传后的URL
else:
print(f"上传失败: {response.text}") # 打印错误信息
return None # 返回None表示上传失败
def generate_filename(extension, timestamp, count):
"""生成带有时间戳和后缀的唯一文件名(例如,2024-04-21-2147-A.jpg)"""
suffix = chr(65 + count) # 65是'A'的ASCII码,生成'A'、'B'等后缀
return f"{timestamp}-{suffix}.{extension}" # 返回生成的文件名
def get_timestamp():
"""获取当前时间戳,格式为YYYY-MM-DD-HHMM"""
return datetime.now().strftime("%Y-%m-%d-%H%M") # 返回格式化的时间戳
def main(file_paths):
"""上传提供的文件路径中的图片并返回成功上传的URL列表"""
timestamp = get_timestamp() # 获取当前时间戳
count = 0 # 初始化计数器
success_urls = [] # 初始化成功上传的URL列表
for file_path in file_paths: # 遍历文件路径列表
extension = os.path.splitext(file_path)[1][1:] # 提取文件扩展名(不带点)
custom_filename = generate_filename(extension, timestamp, count) # 生成自定义文件名
uploaded_url = upload(file_path, custom_filename) # 上传文件
if uploaded_url: # 如果上传成功
success_urls.append(uploaded_url) # 将URL添加到列表中
count += 1 # 增加计数器
if success_urls: # 如果有成功上传的URL
print("Upload Success:") # 打印成功信息
for url in success_urls: # 遍历URL列表
print(url) # 打印每个URL
else:
print("No files were uploaded successfully.") # 打印无文件上传成功的信息
return success_urls # 返回成功上传的URL列表
if __name__ == "__main__":
file_paths = sys.argv[1:]
main(file_paths)
浏览器抓包
-
打开浏览器,进入halo控制台,点击
附件
->上传
->你要上传的分组
->浏览
,然后随意选择一个文件,注意先不要点上传! -
按下
F12
键打开浏览器控制台,选择网络
。 -
点击上传按钮,这个时候会看到控制台出现新内容。点击打开。
-
在其中找到这两个字段:
-
用编辑器打开
uploader.py
,将这三行内容替换为你自己的URL = '你的博客地址' COOKIE = '你的Cookie' GROUP_NAME = '分组名称'
Typora配置
依次点击文件
->偏好设置
->图像
,修改以下值:
如果配置成功,点击验证图片上传选项
应该会看到这样的页面:
之后每次你插入图片就会自动上传图片到你的Halo存储库,并且将图片链接替换为远程链接。