管理markdown图片 cos对象存储
管理markdown图片
源文档

程序替换链接后的新文档

目录结构:
release目录存放程序生成的md文件(已更改 位于项目上级目录中)
cache目录存放1080p缩略图 命名为源文件md5值 jpg格式

assets为自定义目录,在md编辑器中设置添加图片自动复制到该目录,方便集中管理源图片


上传到腾讯对象存储cos
sdk:cos-python-sdk-v5
1.上传文件:
可以指定上传文件夹
upload_file(
Bucket=self.bucket,
LocalFilePath=p, # 本地文件的路径
Key='md/'+name, # 上传到桶之后的文件名
)
2. 获取文件列表信息:
指定文件夹
1.marker来自返回值response['NextMarker']
- :param Marker(string): 从marker开始列出条目.
应该是数字,如请求10条response['NextMarker']=10 下次请求Marker=10就从第10个开始返回
循环获取所有文件列表
3.终止条件:response['IsTruncated'] == 'false'
list_objects(
Bucket=self.bucket,
Prefix=dir_name,
Marker=marker
)
3.图片链接:
https://pic-1305365488.cos.ap-chongqing.myqcloud.com/md/name
name为上传指定的名字
注意需要后缀,且后缀与文件不符可能无法正常显示
文档本地图片处理
1.替换掉本地链接
链接格式

通过正则获取图片链接 uri
'\!\[.*\]\((.*)\)'
替换为网络链接
2.压缩图片
im=Image.open(file)
im.thumbnail((1920,1080))
im=im.convert('RGB')
im.save(img,'JPEG')
完整代码
注意设置环境变量
os.environ.setdefault('key','value')
requests
cos-python-sdk-v5
pillow
pathlib
import hashlib, time, os, pickle,re
from pathlib import Path
from PIL import Image
from env import *
def cal(f):
# 函数运行计时
from functools import wraps
@wraps(f)
def func(*a, **b):
s = time.time()
ret = f(*a, **b)
print('{} 耗时:{:.3f}'.format(f.__name__, time.time()-s))
return ret
return func
def dir_make(arg):
if not os.path.exists(arg):
os.makedirs(arg)
def _get_file(p,index):
# 获取所有文件/夹
ret=[]
for f in os.walk(p):
for i in f[index]:
file= '{}\\{}'.format(f[0], i)
ret.append(file)
return ret
def get_files(p):
return _get_file(p,index=2)
class UploadImg:
bucket='pic-1305365488'
secret_id = os.environ['COS_SECRET_ID'] # 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
secret_key = os.environ['COS_SECRET_KEY'] # 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
def __init__(self) -> None:
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
# 1. 设置用户属性, 包括 secret_id, secret_key, region等。Appid 已在 CosConfig 中移除,请在参数 Bucket 中带上 Appid。Bucket 由 BucketName-Appid 组成
region = 'ap-chongqing' # 替换为用户的 region,已创建桶归属的 region 可以在控制台查看,https://console.cloud.tencent.com/cos5/bucket
# COS 支持的所有 region 列表参见 https://cloud.tencent.com/document/product/436/6224
token = None # 如果使用永久密钥不需要填入 token,如果使用临时密钥需要填入,临时密钥生成和使用指引参见 https://cloud.tencent.com/document/product/436/14048
config = CosConfig(Region=region, SecretId=self.secret_id, SecretKey=self.secret_key, Token=token )
self.client = CosS3Client(config)
def send_file(self,p,func_name=lambda p:Path(p).name,name=''):
if not name:
name=func_name(p)
response = self.client.upload_file(
Bucket=self.bucket,
LocalFilePath=p, # 本地文件的路径
Key='md/'+name, # 上传到桶之后的文件名
)
return response['ETag']
def send_files(self,p):
[self.send_file(i) for i in get_files(p)]
def list_all(self):
dir_name='md'
r=[]
marker=''
while True:
response = self.client.list_objects(
Bucket=self.bucket,
Prefix=dir_name,
Marker=marker
)
r+=response['Contents']
if response['IsTruncated'] == 'false':
break
marker = response['NextMarker']
return r
def show_all(self):
r=self.list_all()
print('上传文件列表')
print('\n'.join([i['Key'] for i in r]))
class Control:
url_pattern='https://pic-1305365488.cos.ap-chongqing.myqcloud.com/md/{}.jpg'
def __init__(self,p) -> None:
self.path=p
self.release_path=Path(p).parent.joinpath('release')
self.cache_path=Path(p).joinpath('cache')
dir_make(self.release_path)
dir_make(self.cache_path)
self.updata=[]
def new_md(self,src,dst):
text=open(src,'r',encoding='utf-8').read()
imgs_path=re.findall('\!\[.*\]\((.*)\)',text)
# 获取文件链接
def img_link(p):
if not os.path.exists(p):
return
id=hashlib.md5(open(p,'rb').read()).hexdigest()
self.updata.append({'path':p,'id':id})
return [p,self.url_pattern.format(id)]
data=[img_link(i) for i in imgs_path]
data=[i for i in data if i]
new_text=text
# 替换链接
for i in data:
old,new=i
new_text=new_text.replace(old,new)
dir_make(Path(dst).parent)
open(dst,'w',encoding='utf-8').write(new_text)
def _thumbnail(self,file,img):
# 缩略图
if os.path.exists(img):
return
try:
im=Image.open(file)
im.thumbnail((1920,1080))
except:
return
im=im.convert('RGB')
im.save(img,'JPEG')
def up_load(self):
# 上传文件 转化为1080p jpg缩略图
client=''
updata=self.updata
# 已上传文件id
data_pickle=self.cache_path.joinpath('uploaddata.pickle')
if data_pickle.exists():
uploaddata=pickle.load( open(data_pickle,'rb'))
else:
uploaddata={}
def f(i):
try:
return re.findall('([^/]+)\.\w+',i['Key'])[0]
except:
return
uploadids= {f(i) for i in uploaddata}
skip=0
for i in updata:
p=i['path']
id=i['id']
if id in uploadids:
skip+=1
continue
if not client:
# 上次数据不足以应付
client=UploadImg()
uploaddata=client.list_all()
pickle.dump(uploaddata,open(data_pickle,'wb'))
uploadids= {f(i) for i in uploaddata}
if id in uploadids:
skip+=1
continue
# 强制jpg缩略图
img=self.cache_path.joinpath(f'{id}.jpg')
self._thumbnail(p,img)
client.send_file(img,name=id+'.jpg' )
print('文件上传完毕:{} 已上传跳过:{}'.format(len(updata)-skip,skip))
@cal
def release(self):
# 制作md副本
p=self.path
len_path=len(p)
dst=self.release_path
md_files=[i for i in get_files(p) if i.endswith('md') and not str(dst) in i]
md_pair_files=[[i,dst.joinpath(i[len_path+1:])] for i in md_files]
[self.new_md(*i) for i in md_pair_files]
print('release done:{}'.format(len(md_pair_files)))
print('upload...')
self.up_load()
control=Control(r'X:\bufferx\OneDrive\文档\笔记')
control.release()

浙公网安备 33010602011771号