动机
typora 是一个很好用的md写作工具, 但是写完之后到某些平台发布的时候, 图片并不能被复制过去,需要手动的再上传本地图片,再排版。十分的麻烦。
因此我需要一个能够自动上传图片, 并显示到md文档的程序. 由于我买了阿里云和oss上传文件服务, 所以用oss 来做就再好不过了.
工程位于: https://gitee.com/xiaofeipapa/python-toolkit
代码
#! /usr/bin/python
# -*- coding: UTF-8 -*-
import logging
import uuid
import oss2
"""
作者: 小肥爬爬
简书: https://www.jianshu.com/u/db796a501972
gitee: https://gitee.com/xiaofeipapa
邮箱: imyunshi@163.com
您可以自由转载此博客文章, 恳请保留原链接, 谢谢!
"""
import os
class AliyunOSS:
def __init__(self, app_key, app_secret, oss_url, bucket_name):
auth = oss2.Auth(app_key, app_secret)
self.bucket = oss2.Bucket(auth, oss_url, bucket_name)
self.url_prefix = 'http://' + bucket_name + '.' + oss_url
logging.info('======= oss init ok')
def make_unique_id(self):
"""
生成唯一的id
:return:
"""
name = str(uuid.uuid4())
name = uuid.uuid5(uuid.NAMESPACE_DNS, name)
name = str(name)
return name
def upload_image_async(self, upload_dto, need_logging=False):
"""
同步方式上传图片
:param upload_dto: UploadFileDto 对象
:return:
"""
headers = {
'Content-Type': upload_dto.content_type,
'x-oss-meta-width': str(upload_dto.width),
'x-oss-meta-height': str(upload_dto.height),
}
# 生成唯一的filename
name = self.make_unique_id()
result = self.bucket.put_object(name, upload_dto.file_data, headers=headers)
if need_logging:
logging.info('http status: {0}'.format(result.status))
logging.info('request_id: {0}'.format(result.request_id))
logging.info('ETag: {0}'.format(result.etag))
logging.info('date: {0}'.format(result.headers['date']))
return name, self.get_full_url(name)
def get_image_meta(self, name):
"""
返回 meta 信息. 不会全部返回阿里云的信息, 只会返回一部分
:param name:
:return:
"""
oss_meta = self.bucket.head_object(name).headers
meta = {
'width': oss_meta['x-oss-meta-width'],
'height': oss_meta['x-oss-meta-height'],
'content_type': oss_meta['content-type']
}
return meta
def upload_file_async(self, file_data, content_type, need_logging=False):
"""
同步方式上传文件
:param upload_dto: UploadFileDto 对象
:return:
"""
headers = {
'Content-Type': content_type,
}
# 生成唯一的filename
name = self.make_unique_id()
result = self.bucket.put_object(name, file_data, headers=headers)
if need_logging:
logging.info('http status: {0}'.format(result.status))
logging.info('request_id: {0}'.format(result.request_id))
logging.info('ETag: {0}'.format(result.etag))
logging.info('date: {0}'.format(result.headers['date']))
return name, self.get_full_url(name)
def get_full_url(self, name):
"""
返回图片的网络路径
:param name:
:return:
"""
return self.url_prefix + '/' + name
def upload_local_file_sync(self, file_path, content_type, need_logging=False):
"""
同步方式上传文件
"""
headers = {
'Content-Type': content_type
}
# 生成唯一的filename
file_ext = os.path.splitext(file_path)[1]
name = self.make_unique_id() + file_ext.lower()
"""
fck!!! 试了很久, 发现是阿里云的文档说明有问题!!!
真正说明在这: https://help.aliyun.com/document_detail/88426.html
"""
# 必须以二进制的方式打开文件,因为需要知道文件包含的字节数。
with open(file_path, 'rb') as fileobj:
fileobj.seek(0) # 0 表示从开始,直到文件结束。
# Tell方法用于返回当前位置。
current = fileobj.tell()
result = self.bucket.put_object(name, fileobj, headers=headers)
if need_logging:
logging.info('http status: {0}'.format(result.status))
logging.info('request_id: {0}'.format(result.request_id))
logging.info('ETag: {0}'.format(result.etag))
logging.info('date: {0}'.format(result.headers['date']))
return name, self.get_full_url(name)
if __name__ == '__main__':
import sys
if len(sys.argv) < 2:
print("调用错误, 图片格式不对")
sys.exit(1)
app_key = ''
app_secret = ''
oss_url = ''
bucket_name = ''
a_oss = AliyunOSS(app_key, app_secret, oss_url, bucket_name)
# 返回值。
url_list = []
for i in range(1, len(sys.argv)):
path = sys.argv[i]
name, url = a_oss.upload_local_file_sync(path, 'image/png', True)
url_list.append(url)
print("Upload Success:")
for url in url_list:
print(url)
只要输入你的app_key 这些信息就可以用了.
配置
将上面的文件保存成 xx.py , 然后在typora的配置里:
image-20210319172548386
将如图圈主的命令改为 :
python3 xx.py
即可. 然后可以点 Test Uploader 进行测试.
Have fun !