import os import re import time from datetime import timedelta import datetime from io import BytesIO from fastapi import Depends, FastAPI, HTTPException, status, UploadFile, APIRouter, File from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from starlette.responses import StreamingResponse, FileResponse from config.config import MinioOperate, SetCache from models.model import * from utils.jwt import authenticate_user, ACCESS_TOKEN_EXPIRE_MINUTES, create_access_token, get_current_active_user, \ fake_users_db # 创建minio对象 minio_class = MinioOperate() # 连接minio minio_client = minio_class.link_minio() # 创建bucket minio_class.create_bucket(["file", "image"]) # 初始化缓存 cache = SetCache(maxsize=128, ttl=100) router = APIRouter() @router.post("/token", response_model=Token) async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()): user = authenticate_user(fake_users_db, form_data.username, form_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) # 设置令牌过期时间 access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) # 创建访问令牌 access_token = create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) return {"access_token": access_token, "token_type": "bearer"} # minio ?上传文件时在重复时,需要修改文件名 @router.post("/file") async def create_file(file: UploadFile = File(...)): timestamp = str(time.time()).ljust(18, "0") uid = re.sub(r"\.", "", timestamp) front, ext = os.path.splitext(file.filename) file_name = uid + ext # 168549427474778.png data = await file.read() file_stream = BytesIO(initial_bytes=data) size = len(data) date = str(datetime.date.today()) object_path = date + "/{}".format(file_name) if (minio_client.put_object( "image", object_path, file_stream, size )): return {"status": 200, "data": [file_name], "msg": ""} else: return {"status": 400, "data": [], "msg": "Post Failed!"} # 图片预览【把后缀jpg去掉也可以变成下载】 # response = StreamingResponse(file_content,media_type='image/jpg) # 图片下载功能 # response = StreamingResponse(file_content, # media_type='application/octet-stream', # headers={"Content-Disposition": f"attachment; filename={uid}"}) @router.get("/file/{uid}") async def download_file(uid: str): try: timestamp, ext = os.path.splitext(uid) timestamp = float(str(float(timestamp) / 10000000).ljust(18, "0")) object_path = str(time.localtime(timestamp).tm_year) + "-" + str(time.localtime(timestamp).tm_mon).rjust(2, "0") + "-" \ + str(time.localtime(timestamp).tm_mday).rjust(2, "0") + "/{}".format(uid) file_obj = minio_client.get_object("image", object_path) if not cache.get(uid): # 添加缓存 # print("第一次获取,添加到缓存") cache.add(uid, file_obj.read()) else: # print("从缓存中找到uid,获取缓存") file_bytes = cache.get(uid) return StreamingResponse(BytesIO(file_bytes), media_type="image/{}".format(ext[1:])) file_content = BytesIO(file_obj.read()) response = StreamingResponse(file_content, media_type='image/{}'.format(ext[1:])) except Exception as e: return {"status": 400, "data": [], "msg": "Get Failed!"} # return response return {"status": 200, "data": [uid], "msg": ""} # 删除 鉴权 current_user: User = Depends(get_current_active_user) @router.delete("/file/{uid}") async def delete_file(uid: str): try: timestamp, ext = os.path.splitext(uid) timestamp = float(str(float(timestamp) / 10000000).ljust(18, "0")) object_path = str(time.localtime(timestamp).tm_year) + "-" + str(time.localtime(timestamp).tm_mon).rjust(2, "0") + "-" \ + str(time.localtime(timestamp).tm_mday).rjust(2, "0") + "/{}".format(uid) minio_client.get_object("image", object_path) minio_client.remove_object("image", object_path) return {"status": 200, "data": [], "msg": "Delete Success!"} except: return {"status": 404, "data": [], "msg": "Not Found"}