123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- from fastapi import APIRouter, Request, Depends,Response,HTTPException,status,Query,UploadFile,File,Form
- from typing import List, Optional
- from fastapi.responses import JSONResponse
- from fastapi.responses import FileResponse
- from sqlalchemy.orm import Session
- from database import get_db
- from config import settings
- from urllib import parse
- # from PIL import Image
- from models import *
- from utils import *
- from common.security import valid_access_token,valid_access_token_role
- import requests
- import hashlib
- import random
- import string
- import json
- import time
- import os
- router = APIRouter()
- UPLOAD_IMAGE_PATH = '/data/upload/img/'
- UPLOAD_mergefile_PATH = '/data/upload/mergefile/'
- @router.post("/upload/upload_img")
- async def upload_img(
- request: Request,
- file: UploadFile = File(...),
- db: Session = Depends(get_db), dependencies=Depends(valid_access_token_role)
- ):
- file_name = file.filename
- # 文件后续名校验
- suffix = os.path.splitext(file_name)[-1]
- if suffix.lower() not in ['.png', '.jpg', '.jpeg']:
- return {
- 'code': 1,
- 'msg': '文件类型不在png,jpg范围内',
- }
- upload_path = UPLOAD_IMAGE_PATH
- file_dir = os.path.join(upload_path, "{}".format("poster"))
- if os.path.exists(file_dir) == False:
- os.makedirs(file_dir)
- file_name = new_guid() + suffix.lower()
- file_path = os.path.abspath("{}/{}".format(file_dir, file_name))
- if os.path.exists(file_path):
- os.remove(file_path)
- content = await file.read()
- with open(file_path, 'wb') as f:
- f.write(content)
- print('file_path:', file_path)
- return {
- 'code': 200,
- 'msg': '上传成功',
- 'data': file_name
- }
- @router.get('/get_img/get_img_by_id/{id}', response_class=FileResponse)
- async def get_poster_by_id(
- request: Request,
- id: str,
- db: Session = Depends(get_db)
- ):
- image_filepath = os.path.abspath(os.path.join(UPLOAD_IMAGE_PATH+'poster/', id )) #+ ".png"
- # print(image_filepath)
- if os.path.exists(image_filepath) == False:
- return {'err':'错误'}
- image_filepath = "./static/img/video_poster.png"
- # else:
- # file_size = os.path.getsize(image_filepath)
- # if file_size > (1024 * 1024 * 1.5): # 1.5M
- # image = Image.open(image_filepath)
- # image.thumbnail((675, 390))
- # image.save(image_filepath, 'png')
- return FileResponse(image_filepath)
- @router.post("/upload/uploadfile")
- async def upload_big_file( request: Request,
- file: UploadFile = File(...),
- chunknumber: str = Query(''),
- identifier: str = Query(''), dependencies=Depends(valid_access_token_role)): # 分片上传文件【用唯一标志符+分片序号】作为文件名
- if not file:
- raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="文件字段缺失")
- if len(chunknumber) == 0 or len(identifier) == 0:
- return {"eroor": "没有传递相关参数"}
- # print(1111)
- task = identifier # 获取文件唯一标识符
- chunk = chunknumber # 获取该分片在所有分片中的序号【客户端设定】
- filename = '%s%s' % (task, chunk) # 构成该分片唯一标识符
- file_dir = f"{UPLOAD_mergefile_PATH}/uploads/"
- if os.path.exists(file_dir) == False:
- os.makedirs(file_dir)
- contents = await file.read() # 异步读取文件
- with open(file_dir+f"{filename}", "wb") as f:
- f.write(contents)
- return {
- 'code': 200,
- 'msg': '成功',
- "filename": file.filename}
- @router.post("/upload/mergefile")
- async def mergefile(identifier: str = Query(''),
- filename: str = Query(''),
- chunkstar: int = Query(0), dependencies=[Depends(valid_access_token_role)]): # 根据唯一标识符合并文件
- if len(filename) == 0 or len(identifier) == 0:
- return {"eroor": "没有传递相关参数"}
- suffix = os.path.splitext(filename)[-1]
- filename = new_guid() + suffix.lower()
- target_filename = filename # 获取上传文件的文件名【保存的文件名】
- task = identifier # 获取文件的唯一标识符
- chunk = chunkstar # 分片序号开始的序号默认=0
- if os.path.isfile(f"{UPLOAD_mergefile_PATH}/uploads/{target_filename}"): # 如果客户端传递过来的文件名在服务器上已经存在,那么另外新建一个【时间戳.后缀名】文件
- t = time.time() # 时间戳
- timeUnix = str(round(t * 1000)) # 毫秒级时间戳
- filesuffix = os.path.splitext(target_filename)[1] # 后缀名
- target_filename = timeUnix + filesuffix # 新文件名【时间戳.后缀名】
- error_i = 0
- chunkfilename = ""
- with open(f"{UPLOAD_mergefile_PATH}/uploads/{target_filename}", 'wb') as target_file: # 创建新文件
- while True: # 循环把分片文件写入新建的文件
- if os.path.isfile(f"{UPLOAD_mergefile_PATH}/uploads/{task}{chunk}"): # 存在这个文件
- try:
- # 分片文件名
- chunkfilename = f"{UPLOAD_mergefile_PATH}/uploads/{task}{chunk}"
- # 按序打开每个分片
- source_file = open(chunkfilename, 'rb')
- # 读取分片内容写入新文件
- target_file.write(source_file.read())
- source_file.close()
- except IOError: # 当分片标志chunk累加到最后,文件夹里面不存在{task}{chunk}文件时,退出循环
- break
- os.remove(f"{UPLOAD_mergefile_PATH}/uploads/{task}{chunk}") # 删除分片文件
- else: # 【如果分片文件上传中途出错,导致中间缺少某个分片文件,跳过它,不退出循环,直到累计缺少次数大于3次,再跳出循环】
- error_i += 1
- if error_i > 3:
- break
- chunk += 1
- os.chmod(f"{UPLOAD_mergefile_PATH}uploads/{target_filename}", 0o664) # linux设置权限0o664、0o400
- return {"code": 200, "filename": f"{target_filename}"}
- @router.get("/download/{filename}")
- async def download_file(filename: str,filenameDesc: str = None, dependencies=[Depends(valid_access_token_role)]):
- """
- 根据提供的文件名下载文件。
- :param filename: 要下载的文件的名称。
- """
- try:
- # 构造文件的完整路径
- file_path = os.path.join(UPLOAD_mergefile_PATH, 'uploads/', filename)
- # 检查文件是否存在
- if not os.path.isfile(file_path):
- raise HTTPException(status_code=404, detail="文件未找到")
- if not filenameDesc:
- filenameDesc = filename
- # 设置文件头部和内容类型
- headers = {
- 'Content-Disposition': f'attachment; filename={filenameDesc}'
- }
- # 使用FileResponse返回文件流
- return FileResponse(
- path=file_path,
- headers=headers,
- media_type='application/octet-stream' # 可以按需更改为适当的MIME类型
- )
- except HTTPException as e:
- raise e
- except Exception as e:
- # 处理其他异常情况
- raise HTTPException(status_code=500, detail=str(e))
|