大家好~我是米洛

我正在从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下载文件的文章吧。

FastApi下载文件

或者直接去github查看源码~

今天的内容就介绍到这里了,下一节卷oss的用途。

测试平台系列(90) 编写oss客户端的更多相关文章

  1. 测试平台系列(91) 编写oss管理页面

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节我们编写好了oss相关 ...

  2. 测试平台系列(80) 封装Redis客户端

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ...

  3. 测试平台系列(81) 编写在线执行Redis功能

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们牛刀小试,编写了 ...

  4. 测试平台系列(79) 编写Redis配置功能(下)

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们提出了优化Dao ...

  5. 测试平台系列(92) 让http请求支持文件上传

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节呢,我们编写了oss的 ...

  6. 测试平台系列(83) 前置条件支持Redis语句

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上节我们打了个野,解决了一 ...

  7. 测试平台系列(85) 把redis运用到实战中

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们让支持了前置条件 ...

  8. 测试平台系列(71) Python定时任务方案

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 定时任务 定时任务,顾名思义: ...

  9. 测试平台系列(72) 了解ApScheduler基本用法

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们调研了一下市面上 ...

随机推荐

  1. python 定义函数关键字def 简单介绍

    一  在类中定义的def # python中def 是用来干什么的? # 可以定义函数,就是定义一个功能. class People(): def __init__(self): print(&quo ...

  2. ApacheCN 深度学习译文集 20201229 更新

    新增了七个教程: TensorFlow 和 Keras 应用开发入门 零.前言 一.神经网络和深度学习简介 二.模型架构 三.模型评估和优化 四.产品化 TensorFlow 图像深度学习实用指南 零 ...

  3. Java微服务监控及与普罗米集成

    一.    背景说明 Java服务级监控用于对每个应用占用的内存.线程池的线程数量.restful调用数量和响应时间.JVM状态.GC信息等进行监控,并可将指标信息同步至普罗米修斯中集中展示和报警.网 ...

  4. go 把固定长度的数字写入字节切片 (byte slice),然后从字节切片中读取到并赋值给一个变量:

    // write v := uint32(500) buf := make([]byte, 4) binary.BigEndian.PutUint32(buf, v) // read x := bin ...

  5. table 增加或删除一行

    转载请注明来源:https://www.cnblogs.com/hookjc/ <HTML><SCRIPT LANGUAGE="JScript">funct ...

  6. linux上printf出带颜色字体

    转载请注明来源:https://www.cnblogs.com/hookjc/ 统一定义: #define NONE         "\033[m"  #define RED   ...

  7. iOS App 架构文章推荐

    iOS应用开发架构 iOS应用架构谈系列 阿里技术沙龙 2.2.1. Hybrid App 2.2.2. taobao 客户端架构 2.2.3. alipay 客户端架构   iOS APP 架构漫谈 ...

  8. iOS应用跳转至app store 评分页

    小功能之去AppStore评分 #pragma mark - 去AppStore评分 -(void)goToAppStore { NSString *str = [NSString stringWit ...

  9. FastJSON解析Json字符串(反序列化为List、Map)

    在日常开发与数据库打交道的时候,常有以Json格式的字符串存储到数据库的情况,当在Java程序中获取到对应的Json格式的String字符串后,如何才能转换为我们想要的数据格式(比如转换成Java中的 ...

  10. 【BZOJ5492】校园旅行(图论 搜索优化)

    题目链接 大意 给出\(N\)个点,\(M\)条边的一张图,其中每个点都有一个0或1的颜色. 再给出\(Q\)个询问,每次询问查询两个点之间是否存在一条路径,使得路径上的颜色组成的01字符串是一个回文 ...