前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hexo -34- 为自己的 Nginx 图床搭建 Python 上传服务适配 PicGo

Hexo -34- 为自己的 Nginx 图床搭建 Python 上传服务适配 PicGo

作者头像
为为为什么
发布2022-08-04 14:03:42
4110
发布2022-08-04 14:03:42
举报
文章被收录于专栏:又见苍岚

通过 Nginx 建立自己的图床后,之前的 Picgo 无法使用,导致在文档中插入图片十分不便,本文记录自己搭建 Python 后端服务来为自己的图床适配 Picgo 的方法。

背景

  • 已经成功搭建 Nginx 图床
  • PicGo 上传图像十分方便,可以将图像数据放在数据包中向指定服务器发送
  • 此时我们有服务器,有工具,只差中间接洽的桥梁
  • Python 自带简易后端 flask,可以方便地获取数据包并返回我们需要的数据

实现要点

不同的使用者可能有不同的需求,我提供自己的实现思路,供大家参考。

调试
  • 链路没有打通前调试十分重要,具体方法为:
    • 在服务器安装 Python
    • 本地 VScode 远程调试服务器代码
    • 运行 flask 服务,本地使用 Picgo 发送数据包进行调试
思路
  • 服务器上使用 Python 开启 flask 监听特定端口
  • 服务器开通防火墙暴露端口
  • 本地 Picgo 向服务器地址发送数据包
  • flask 接收、解析数据,按照需求处理业务逻辑,返回文件 url
  • 将该服务设置为服务器开机启动服务,之后便再也不用操心无人接管 Picgo 数据包

实现方法

PicGo 端配置
  • 建议使用 Picgo 的自定义上传插件
  • 配置自定义 Web 图床设置

API 地址为服务器地址,后面 / 后可以接一段字符作为输入参数,我将其作为存放文件的子文件夹 post 参数名为文件所在参数名 其余建议不要填,不然会上传失败,不知道原因

服务器端配置
  • 引入库
代码语言:javascript
复制
from flask import Flask, request
import io
from PIL import Image
import mtutils as mt
import numpy as np

  • 配置信息
代码语言:javascript
复制
key_para = 'file'							# Picgo 映射字段
save_root = 'path-to-your-file'				# 数据存储文件夹
host = 'https://1.1.1.1'					# flask 监听IP,建议使用 0.0.0.0
default_name = 'imgbed'						# 默认二级文件夹名称
log_file_path = '/usr/local/imgbed/log.log'	# 日志存放路径
port = '6789'								# flask 监听端口

  • 初始化 flask app
代码语言:javascript
复制
app = Flask(__name__)
app.last_file = None
# 日志对象
app.logger = mt.log_init(log_file_path)

  • 核心数据解析于业务逻辑
代码语言:javascript
复制
def specific_path(save_to):
	# 获取数据包文件
    file = request.files[key_para]
    file_content = file.read()
	# 存放文件的文件夹
    save_dir = mt.OS_join(save_root, save_to)
    mt.dir_check(save_dir)

    # 此处我将非 jpg 图像压缩为 jpg 图保存,其余文件类型直接保存
    # check if a jpg Image file
    if file.content_type[:5].lower() == 'image' and file.content_type[-4:].lower() not in ['/jpg', 'jpeg']:
        # is image
        image_obj = Image.open(io.BytesIO(file_content))

        # to jpg
        file_name = str(mt.Path(file.filename).with_suffix('.jpg'))
        save_path = mt.OS_join(save_dir, file_name)
        image_save_path = mt.Path(save_path)
        image_save_path.parent.mkdir(parents=True, exist_ok=True)
        # 保存 jpg 图像
        image_obj.save(str(image_save_path))
        # 记录日志
        app.logger(f'Transfer and save image to {save_path}.')
    else:
        file_name = file.filename
        save_path = mt.OS_join(save_dir, file_name)
        obj = open(save_path, mode='wb')
        # 保存文件
        obj.write(file_content)
        # 记录日志
        app.logger(f'Save file to {save_path}.')

    app.last_file = save_path
    back_link = mt.OS_join(host, 'HexoFiles', save_to, file_name)
    return back_link

  • 之前使用 PicGo 传图时经常遇到想要删除刚刚上传图像的需求,此处加了相关功能
代码语言:javascript
复制
if '__del__' in save_to:
    res_str = 'nothing happened.'
    if app.last_file is not None:
        mt.remove_file(app.last_file)
        res_str = f"File deleted {app.last_file}"
        app.logger(res_str)
        app.last_file = None
    return res_str

在 API 链接里 / 后的字符串中如包含 __del__ 则删除刚刚上传的图像,返回操作结果

  • 如果没有配置 API 后的文件夹作为参数,使用默认二级文件夹
代码语言:javascript
复制
@app.route("/", methods=['GET','POST'])
def default_save_path():
    default_path = default_name
    return specific_path(default_path)

  • 运行服务
代码语言:javascript
复制
if __name__ == '__main__':
    app.logger("**************** Sever Start *******************")
    app.run('0.0.0.0', port=port)
    pass

  • 完整代码
代码语言:javascript
复制
from flask import Flask, request
import io
from PIL import Image
import mtutils as mt
import numpy as np


key_para = 'file'
save_root = 'path-to-your-file'
host = 'https://1.1.1.1'
default_name = 'imgbed'
log_file_path = '/usr/local/imgbed/log.log'
port = '6789'


app = Flask(__name__)
app.last_file = None
app.logger = mt.log_init(log_file_path)


@app.route("/<save_to>", methods=['GET','POST'])
def specific_path(save_to):

    if '__del__' in save_to:
        res_str = 'nothing happened.'
        if app.last_file is not None:
            mt.remove_file(app.last_file)
            res_str = f"File deleted {app.last_file}"
            app.logger(res_str)
            app.last_file = None
        return res_str

    file = request.files[key_para]
    file_content = file.read()

    save_dir = mt.OS_join(save_root, save_to)
    mt.dir_check(save_dir)

    # check if a jpg Image file
    if file.content_type[:5].lower() == 'image' and file.content_type[-4:].lower() not in ['/jpg', 'jpeg']:
        # is image
        image_obj = Image.open(io.BytesIO(file_content))

        # to jpg
        file_name = str(mt.Path(file.filename).with_suffix('.jpg'))
        save_path = mt.OS_join(save_dir, file_name)
        image_save_path = mt.Path(save_path)
        image_save_path.parent.mkdir(parents=True, exist_ok=True)
        image_obj.save(str(image_save_path))
        app.logger(f'Transfer and save image to {save_path}.')
    else:
        file_name = file.filename
        save_path = mt.OS_join(save_dir, file_name)
        obj = open(save_path, mode='wb')
        obj.write(file_content)
        app.logger(f'Save file to {save_path}.')

    app.last_file = save_path
    back_link = mt.OS_join(host, 'HexoFiles', save_to, file_name)
    return back_link


@app.route("/", methods=['GET','POST'])
def default_save_path():
    default_path = default_name
    return specific_path(default_path)


if __name__ == '__main__':
    app.logger("**************** Sever Start *******************")
    app.run('0.0.0.0', port=port)
    pass

设置开机运行服务
  • 开机启动服务
代码语言:javascript
复制
[Unit]
Description = Service for uploading file to target dir
After = network.target

[Service]
ExecStart = path-to-your-python main.py
WorkingDirectory = /usr/local/imgbed/
StandardOutput = inherit
StandardError = inherit
Restart = always
User = lighthouse

[Install]
WantedBy=multi-user.target

参考资料

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 实现要点
    • 调试
      • 思路
      • 实现方法
        • PicGo 端配置
          • 服务器端配置
            • 设置开机运行服务
            • 参考资料
            相关产品与服务
            远程调试
            远程调试(Remote Debugging,RD)在云端为用户提供上千台真实手机/定制机/模拟器设备,快速实现随时随地测试。运用云测技术对测试方式、操作体验进行了优化,具备多样性的测试能力,包括随时截图和记录调试日志,稳定的支持自动化测试, 设备灵活调度,用例高效执行, 快速定位产品功能和兼容性问题。云手机帮助应用、移动游戏快速发现和解决问题,节省百万硬件费用,加速敏捷研发流程。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档