测试平台系列(90) 编写oss客户端
大家好~我是
米洛
!
我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程
,希望大家多多支持。
欢迎关注我的公众号米洛的测开日记
,获取最新文章教程!
回顾
上一节我们编写了在线执行测试计划
功能,并稍微改了下报告页面。那其实我们之前的内容都是有很多坑在里面的。
比如http请求只支持了json和form,没有支持文件上传
的请求,甚至有一些crud的功能都没有太完善。
不过不要紧,我的想法还是先创造
,再完善。当然也不是盲目创造,也得提前预判好后面的走向。
为什么要用oss
pity里面oss打算用在2个地方,第一个就是一些静态资源图片。比方说项目图片
,用户头像
。
另一个地方就是上文说的,测试文件上传接口的时候,我们需要测试文件
。这些文件怎么来,怎么管理?都得借助oss来完成。
目前以我熟悉的oss为例,打算支持以下几种oss:
阿里云oss
腾讯云cos ~~腾讯云cos~~(无账号)
七牛云(免费,我能给展示demo)
gitee(免费)
其中阿里云和腾讯云由于都是
付费产品
,博主还是买不起的。所以可能需要有对应的测试账号,在此感谢小右(Mini-Right)的帮助,给了我一个阿里云的测试账号,保证了crud能正常进行。如果需要我实现其他oss客户端,请带上对应的测试账号私信我哈。
测试网站的数据估计会用
gitee
或者七牛云
。
说明
关于文件管理这块,由于时间关系,我暂时不会
落一张表与oss数据进行关联,主要目的是为了节省时间
。
表关联可以作为二期工程。
编写oss基类
新建app.middleware.oss.oss_file.py
由于咱们支持多种oss客户端,所以包装好一个抽象类(类似go的interface)等着各个oss客户端
去实现之。
from abc import ABC, abstractmethod
from typing import ByteString
class OssFile(ABC):
@abstractmethod
def create_file(self, filepath: str, content: ByteString):
pass
@abstractmethod
def update_file(self, filepath: str, content: ByteString):
pass
@abstractmethod
def delete_file(self, filepath: str):
pass
@abstractmethod
def list_file(self):
pass
@abstractmethod
def download_file(self, filepath):
pass
抽象类没有具体的实现,只有方法的定义,目的是为了限制子类的方法,即必须实现基类中定义的方法。
总结了一下,必须有增删改查下载
5种方法。
编写AliyunOss实现
新建app.middleware.oss.aliyun.py
from typing import ByteString
import oss2
from app.middleware.oss.files import OssFile
class AliyunOss(OssFile):
def __init__(self, access_key_id: str, access_key_secret: str, endpoint: str, bucket: str):
auth = oss2.Auth(access_key_id=access_key_id,
access_key_secret=access_key_secret)
# auth = oss2.AnonymousAuth()
self.bucket = oss2.Bucket(auth, endpoint, bucket)
def create_file(self, filepath: str, content: ByteString):
self.bucket.put_object(filepath, content)
def update_file(self, filepath: str, content: ByteString):
self.bucket.put_object(filepath, content)
def delete_file(self, filepath: str):
self.bucket.delete_object(filepath)
def list_file(self):
ans = []
for obj in oss2.ObjectIteratorV2(self.bucket):
ans.append(dict(key=obj.key, last_modified=obj.last_modified,
size=obj.size, owner=obj.owner))
return ans
def download_file(self, filepath):
if not self.bucket.object_exists(filepath):
raise Exception(f"oss文件: {filepath}不存在")
return self.bucket.get_object(filepath)
AliyunOss继承了OssFile,构造方法获取阿里云的身份信息,并验证。最后读取bucket,这bucket我理解的是一块区域
,你的文件都存储在这块区域里面,我们就叫他F盘吧。
其他的方法很简单,基本上是调用对应的api,去做crud操作。oss没有文件夹
的概念,都是统一用路径来存储文件地址的,比如:
woody/github.txt
这个文件路径可以理解为,woody目录下的github.txt
文件。
编写获取客户端方法
app.middleware.oss._\_init__.py
from app.core.configuration import SystemConfiguration
from app.middleware.oss.aliyun import AliyunOss
from app.middleware.oss.files import OssFile
class OssClient(object):
_client = None
@classmethod
def get_oss_client(cls) -> OssFile:
"""
通过oss配置拿到oss客户端
:return:
"""
if OssClient._client is None:
cfg = SystemConfiguration.get_config()
oss_config = cfg.get("oss")
access_key_id = oss_config.get("access_key_id")
access_key_secret = oss_config.get("access_key_secret")
bucket = oss_config.get("bucket")
endpoint = oss_config.get("endpoint")
if oss_config is None:
raise Exception("服务器未配置oss信息, 请在configuration.json中添加")
if oss_config.get("type").lower() == "aliyun":
return AliyunOss(access_key_id, access_key_secret, endpoint, bucket)
raise Exception("不支持的oss类型")
return OssClient._client
我们在configuration.json配置oss信息,接着每次都从OssClient获取客户端即可。
编写后端接口
from fastapi import APIRouter, File, UploadFile
from app.handler.fatcory import PityResponse
from app.middleware.oss import OssClient
router = APIRouter(prefix="/oss")
@router.post("/upload")
async def create_oss_file(filepath: str, file: UploadFile = File(...)):
try:
file_content = await file.read()
# 获取oss客户端
client = OssClient.get_oss_client()
client.create_file(filepath, file_content)
return PityResponse.success()
except Exception as e:
return PityResponse.failed(f"上传失败: {e}")
@router.get("/list")
async def list_oss_file():
try:
client = OssClient.get_oss_client()
files = client.list_file()
return PityResponse.success(files)
except Exception as e:
return PityResponse.failed(f"获取失败: {e}")
@router.get("/delete")
async def delete_oss_file(filepath: str):
try:
client = OssClient.get_oss_client()
client.delete_file(filepath)
return PityResponse.success()
except Exception as e:
return PityResponse.failed(f"删除失败: {e}")
@router.post("/update")
async def update_oss_file(filepath: str, file: UploadFile = File(...)):
"""
更新oss文件,路径不能变化
:param filepath:
:param file:
:return:
"""
try:
client = OssClient.get_oss_client()
file_content = await file.read()
client.update_file(filepath, file_content)
return PityResponse.success()
except Exception as e:
return PityResponse.failed(f"删除失败: {e}")
方法很简单,文件路径在url参数里边,文件的话,利用fastapi里面的File和UploadFile皆可获取到上传的文件。
注意,必须先安装python-multipart库配合文件上传
测试一下
成功读取到了oss的文件信息,但下载接口
好像忘记下载文件相关内容了,那么参考我的上一篇FsatApi下载文件的文章
吧。
或者直接去github查看源码~
今天的内容就介绍到这里了,下一节卷oss的用途。
测试平台系列(90) 编写oss客户端的更多相关文章
- 测试平台系列(91) 编写oss管理页面
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节我们编写好了oss相关 ...
- 测试平台系列(80) 封装Redis客户端
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ...
- 测试平台系列(81) 编写在线执行Redis功能
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们牛刀小试,编写了 ...
- 测试平台系列(79) 编写Redis配置功能(下)
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们提出了优化Dao ...
- 测试平台系列(92) 让http请求支持文件上传
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节呢,我们编写了oss的 ...
- 测试平台系列(83) 前置条件支持Redis语句
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上节我们打了个野,解决了一 ...
- 测试平台系列(85) 把redis运用到实战中
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们让支持了前置条件 ...
- 测试平台系列(71) Python定时任务方案
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 定时任务 定时任务,顾名思义: ...
- 测试平台系列(72) 了解ApScheduler基本用法
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们调研了一下市面上 ...
随机推荐
- jstl split 分割字符串?
1. 在已经获得数据的前提下,对数据进行分割,分割后的结果是一个数组,可以通过数组获得我们需要的数据 2. value 是获得值 需要${} 的方式获取, var 是设置变量. var = " ...
- docker常用命令、镜像命令、容器命令、数据卷,使用dockerFile创建镜像,dockefile的语法规则。
一.docker常用命令? 1. 常用帮助命令 1.1 docker的信息以及版本号 /* docker info 查看docker的信息 images2 docker本身就是一个镜像. docker ...
- 「ZJOI2017」树状数组
「ZJOI2017」树状数组 以下均基于模2意义下,默认\(n,m\)同阶. 熟悉树状数组的应该可以发现,这题其实是求\(l-1\)和\(r\)位置值相同的概率. 显然\(l=1\)的情况需要特盘. ...
- 线程池与Callable接口
定义: 一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源. 使用方法 public void lockDemo() throws Inter ...
- JAVA之容器(转)
一.概览 容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表. Collection 1. Set TreeSe ...
- Swift可选类型
可选类型 可选类型的介绍 注意: 可选类型时swift中较理解的一个知识点 暂时先了解,多利用Xcode的提示来使用 随着学习的深入,慢慢理解其中的原理和好处 概念: 在OC开发中,如果一个变量暂停不 ...
- 基于redis实现tomcat的session会话保持 (转)
出处:https://cloud.tencent.com/developer/article/1402997 基于redis实现tomcat的session会话保持 在实际生产中,我们经常部署应用服务 ...
- js正则表达式 未提交进行验证
转载请注明来源:https://www.cnblogs.com/hookjc/ function SetInputMust(){ /*var varr=idstr.split(','); idstr ...
- shell脚本之数组基本操作及排序
数组的基本操作及排序 1.数组定义方法: ( 6 7 9 4 3 2) 0 1 2 3 4 5 #下标号 方法一: 数组名=(value0 value1 value2 -) 方法二: 数组名=([0] ...
- KubeSphere单节点(all-in-one)平台搭建记录
KubeSphere单节点(all-in-one)平台搭建记录 目录 KubeSphere单节点(all-in-one)平台搭建记录 一.主机准备 1.1 主机配置 1.2 环境准备 二.下载kube ...