107 lines
4.3 KiB
Python
107 lines
4.3 KiB
Python
#!/usr/bin/python
|
||
# -*- coding: utf-8 -*-
|
||
# @version : 1.0
|
||
# @Create Time : 2022/4/28 22:32
|
||
# @File : aliyun_oss.py
|
||
# @IDE : PyCharm
|
||
# @desc : 阿里云对象存储
|
||
|
||
import os.path
|
||
from fastapi import UploadFile
|
||
from pydantic import BaseModel
|
||
import oss2 # 安装依赖库:pip install oss2
|
||
from oss2.models import PutObjectResult
|
||
from core.exception import CustomException
|
||
from core.logger import logger
|
||
from utils import status
|
||
from utils.file.file_manage import FileManage
|
||
from utils.file.file_base import FileBase
|
||
|
||
|
||
class BucketConf(BaseModel):
|
||
accessKeyId: str
|
||
accessKeySecret: str
|
||
endpoint: str
|
||
bucket: str
|
||
baseUrl: str
|
||
|
||
|
||
class AliyunOSS(FileBase):
|
||
"""
|
||
阿里云对象存储
|
||
|
||
常见报错:https://help.aliyun.com/document_detail/185228.htm?spm=a2c4g.11186623.0.0.6de530e5pxNK76#concept-1957777
|
||
官方文档:https://help.aliyun.com/document_detail/32026.html
|
||
|
||
使用Python SDK时,大部分操作都是通过oss2.Service和oss2.Bucket两个类进行。
|
||
oss2.Service类用于列举存储空间。
|
||
oss2.Bucket类用于上传、下载、删除文件以及对存储空间进行各种配置。
|
||
"""
|
||
|
||
def __init__(self, bucket: BucketConf):
|
||
# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
|
||
auth = oss2.Auth(bucket.accessKeyId, bucket.accessKeySecret)
|
||
# yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
|
||
# 填写Bucket名称。
|
||
self.bucket = oss2.Bucket(auth, bucket.endpoint, bucket.bucket)
|
||
self.baseUrl = bucket.baseUrl
|
||
|
||
async def upload_image(self, path: str, file: UploadFile, max_size: int = 10) -> str:
|
||
"""
|
||
上传图片
|
||
|
||
:param path: path由包含文件后缀,不包含Bucket名称组成的Object完整路径,例如abc/efg/123.jpg。
|
||
:param file: 文件对象
|
||
:param max_size: 图片文件最大值,单位 MB,默认 10MB
|
||
:return: 上传后的文件oss链接
|
||
"""
|
||
# 验证图片类型
|
||
await self.validate_file(file, max_size, self.IMAGE_ACCEPT)
|
||
# 生成文件路径
|
||
path = self.generate_relative_path(path, file.filename)
|
||
file_data = await file.read()
|
||
return await self.__upload_file_to_oss(path, file_data)
|
||
|
||
async def upload_video(self, path: str, file: UploadFile, max_size: int = 100) -> str:
|
||
"""
|
||
上传视频
|
||
|
||
:param path: path由包含文件后缀,不包含Bucket名称组成的Object完整路径,例如abc/efg/123.jpg。
|
||
:param file: 文件对象
|
||
:param max_size: 视频文件最大值,单位 MB,默认 100MB
|
||
:return: 上传后的文件oss链接
|
||
"""
|
||
# 验证图片类型
|
||
await self.validate_file(file, max_size, self.VIDEO_ACCEPT)
|
||
# 生成文件路径
|
||
path = self.generate_relative_path(path, file.filename)
|
||
file_data = await file.read()
|
||
return await self.__upload_file_to_oss(path, file_data)
|
||
|
||
async def upload_file(self, path: str, file: UploadFile) -> str:
|
||
"""
|
||
上传文件
|
||
|
||
:param path: path由包含文件后缀,不包含Bucket名称组成的Object完整路径,例如abc/efg/123.jpg。
|
||
:param file: 文件对象
|
||
:return: 上传后的文件oss链接
|
||
"""
|
||
path = self.generate_relative_path(path, file.filename)
|
||
file_data = await file.read()
|
||
return await self.__upload_file_to_oss(path, file_data)
|
||
|
||
async def __upload_file_to_oss(self, path: str, file_data: bytes) -> str:
|
||
"""
|
||
上传文件到OSS
|
||
|
||
:param path: path由包含文件后缀,不包含Bucket名称组成的Object完整路径,例如abc/efg/123.jpg。
|
||
:param file_data: 文件数据
|
||
:return: 上传后的文件oss链接
|
||
"""
|
||
result = self.bucket.put_object(path, file_data)
|
||
assert isinstance(result, PutObjectResult)
|
||
if result.status != 200:
|
||
logger.error(f"文件上传到OSS失败,状态码:{result.status}")
|
||
raise CustomException("上传文件失败", code=status.HTTP_ERROR)
|
||
return self.baseUrl + path
|