Typora是我非常喜欢的Markdown编辑器,它支持“上传图像”的功能(即写文章时,插入图片自动将其上传至图床),是我们可以更快捷的分享文档,不至于每次都需要文档加图片一起发送。
网上文档多为使用IPic、uPic、PicG等软件的方式,我们需要下载软件,比较繁琐。所以我自定义了一个脚本,让工作变得更加简单。
一、原理
将本地图片上传至图床,这个过程本质上来说就是一条HTTP请求,具体流程如下
所以,我们只需要使用一个云服务器当服务端,本地当客户端就能够很简单的搭建我们自己的图床
二、服务端搭建
服务端项目运行与一个文件夹中,我的文件夹为/usr/local/gao/typora
其中img
为图片存储地址,img_server.log
为服务端地址,img_server.py
为服务端代码
需要环境:
python3
#base64
pip3 install pybase64
#flask
pip3 install flask
具体代码如下:
import base64
from flask import Flask, request,make_response
app = Flask(__name__)
BASE_URL = '/'
IMG_PATH="/usr/local/gao/typora/img/" #图片实际存储地址
@app.route(BASE_URL,methods=['GET', 'POST'])
def test_post():
#图片上传功能实现
filename = request.form.get("filename")
message = request.form.get("message")
content = request.form.get("content")
app.logger.info(message+filename)
img = base64.urlsafe_b64decode(content)
file = IMG_PATH+filename
with open(file, "wb") as f:
f.write(img)
return "http://服务器IP:999/img/"+filename #服务器返回数据(图片访问地址)
@app.route('/img/<string:filename>', methods=['GET'])
def display_img(filename):
#图片访问功能实现
if request.method == 'GET':
if filename is None:
pass
else:
image_data = open(IMG_PATH+ filename, "rb").read()
response = make_response(image_data)
response.headers['Content-Type'] = 'image/jpg'
return response
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=999)
需要更改内容为:
-
图片实际存储位置:第6行
IMG_PATH="/usr/local/gao/typora/img/" #图片实际存储地址
-
图片返回信息
return "http://服务器IP:999/img/"+filename #服务器返回数据(图片访问地址)
部署运行:
-
到达自己的部署路径
cd /usr/local/gao/typora
-
运行代码
nohup python3 img_server.py > img_server.log 2>&1 &
三、客户端搭建
客户端项目也运行与本地的一个文件夹中,我的文件夹为D:\softare\myScript
其中temp
为图片中间文件,用于图片压缩(占很小磁盘内存),upload_image.py
为客户端代码
需要环境:
python3
#base64
pip3 install pybase64
#requests
pip3 install requests
#PTL
pip3 install pillow
#其他估计系统自带
具体代码如下:
import sys
import base64
import hashlib
import time
import requests
import urllib.parse
import os
from PIL import Image
from PIL import ImageFile
def compress_image(in_file, mb=1000000, quality=85, k=0.9):
"""不改变图片尺寸压缩到指定大小
:param in_file: 压缩文件保存地址
:param mb: 压缩目标,默认1000000byte
:param k: 每次调整的压缩比率
:param quality: 初始压缩比率
:return: 压缩文件地址,压缩文件大小
"""
o_size = os.path.getsize(in_file) # 函数返回为字节数目
# print('before_size:{} after_size:{}'.format(o_size, mb))
if o_size <= mb:
return in_file
ImageFile.LOAD_TRUNCATED_IMAGES = True # 防止图像被截断而报错
temp_file="D:/softare/myScript/temp/temp."+in_file.split(".")[-1] #中间文件路径
im = Image.open(in_file)
try:
im.save(temp_file)
except Exception as e:
print(e)
while o_size > mb:
im = Image.open(temp_file)
x, y = im.size
out = im.resize((int(x*k), int(y*k)), Image.ANTIALIAS) # 最后一个参数设置可以提高图片转换后的质量
try:
out.save(temp_file, quality=quality) # quality为保存的质量,从1(最差)到95(最好),此时为85
except Exception as e:
print(e)
break
o_size = os.path.getsize(temp_file) ##1024
return temp_file
def main():
target = " http://服务器IP:999"
message = 'typora上传图片 ' #自定义上传的信息,使服务端日志更清晰
param = [urllib.parse.unquote(par, 'utf8') for par in sys.argv] # 把url编码转换成中文
param.__delitem__(0) # 第一个参数是脚本文件本身
if len(param) > 0:
if not os.path.exists(param[0]): # 通过判断第一个参数是不是文件来判断是否加了参数 ${filename}
param.__delitem__(0)
for i in range(0, len(param)):
file=compress_image(param[i])#压缩图片,使其保持在1mb一下,防止访问过慢
# file=param[i] #不压缩图片
with open(file, "rb") as f:
content = base64.b64encode(f.read())
filename=str(int(time.time()))+"_"+hashlib.md5(content).hexdigest() + param[i][param[i].rfind('.'):]
data = { 'message': message, 'content': content,'filename':filename}
res = requests.post(target, data)
print(res.status_code)
if res.status_code == 200:
print(res.text)
else:
print('Error uploading Gitee, please check')
if __name__ == '__main__':
main()
需要更改内容为:
-
自己服务器的IP:第46行
target = " http://服务器IP:999"
-
中间文件的路径:第25行
temp_file="D:/softare/myScript/temp/temp."+in_file.split(".")[-1]#中间文件路径
部署运行:
-
移动到自己的文件夹中
-
建temp文件夹
-
测试:
python D:\softare\myScript\upload_image.py "C:\\WINDOWS\\Temp/typora-icon2.png"
如果结果类似如下则可行:
200 http://服务器IP:999/img/1657853679_484e0d9f4c08f524f8a9fd5892f622ff.png
四、typora配置
-
打开typora,点击
文件-偏好设置
,进入设置 -
点击图像,进入图像设置
-
点击上传服务选择
Custom Command
在下面命令添加
python D:\softare\myScript\upload_image.py
-
配置图片自动上传
-
点击插入图片时,选择上传图片
-
勾选如下选项
-