Skip to content

Commit 1920729

Browse files
committed
Add local upload
1 parent bfc0c77 commit 1920729

File tree

18 files changed

+159
-32
lines changed

18 files changed

+159
-32
lines changed

backend/app/admin/api/v1/sys/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from backend.app.admin.api.v1.sys.menu import router as menu_router
1111
from backend.app.admin.api.v1.sys.role import router as role_router
1212
from backend.app.admin.api.v1.sys.token import router as token_router
13+
from backend.app.admin.api.v1.sys.upload import router as upload_router
1314
from backend.app.admin.api.v1.sys.user import router as user_router
1415

1516
router = APIRouter(prefix='/sys')
@@ -23,3 +24,4 @@
2324
router.include_router(user_router, prefix='/users', tags=['系统用户'])
2425
router.include_router(data_rule_router, prefix='/data-rules', tags=['系统数据权限规则'])
2526
router.include_router(token_router, prefix='/tokens', tags=['系统令牌'])
27+
router.include_router(upload_router, prefix='/upload', tags=['系统上传'])
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
from typing import Annotated
5+
6+
from fastapi import APIRouter, File, UploadFile
7+
8+
from backend.common.dataclasses import UploadUrl
9+
from backend.common.enums import FileType
10+
from backend.common.response.response_schema import ResponseSchemaModel, response_base
11+
from backend.common.security.jwt import DependsJwtAuth
12+
from backend.utils.file_ops import file_verify, upload_file
13+
14+
router = APIRouter()
15+
16+
17+
@router.post('/image', summary='上传图片', dependencies=[DependsJwtAuth])
18+
async def upload_image(file: Annotated[UploadFile, File()]) -> ResponseSchemaModel[UploadUrl]:
19+
file_verify(file, FileType.image)
20+
filename = await upload_file(file)
21+
return response_base.success(data={'url': f'/static/upload/{filename}'})
22+
23+
24+
@router.post('/video', summary='上传视频', dependencies=[DependsJwtAuth])
25+
async def upload_video(file: Annotated[UploadFile, File()]) -> ResponseSchemaModel[UploadUrl]:
26+
file_verify(file, FileType.video)
27+
filename = await upload_file(file)
28+
return response_base.success(data={'url': f'/static/upload/{filename}'})

backend/app/generator/conf.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,12 @@
22
# -*- coding: utf-8 -*-
33
from functools import lru_cache
44

5-
from pydantic_settings import BaseSettings, SettingsConfigDict
6-
7-
from backend.core.path_conf import BasePath
5+
from pydantic_settings import BaseSettings
86

97

108
class GeneratorSettings(BaseSettings):
119
"""Admin Settings"""
1210

13-
model_config = SettingsConfigDict(env_file=f'{BasePath}/.env', env_file_encoding='utf-8', extra='ignore')
14-
1511
# 模版目录
1612
TEMPLATE_BACKEND_DIR_NAME: str = 'py'
1713

backend/common/dataclasses.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,8 @@ class TokenPayload:
6161
id: int
6262
session_uuid: str
6363
expire_time: datetime
64+
65+
66+
@dataclasses.dataclass
67+
class UploadUrl:
68+
url: str

backend/common/enums.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ class UserSocialType(StrEnum):
103103
linuxdo = 'LinuxDo'
104104

105105

106+
class FileType(StrEnum):
107+
"""文件类型"""
108+
109+
image = 'image'
110+
video = 'video'
111+
112+
106113
class GenModelMySQLColumnType(StrEnum):
107114
"""代码生成模型列类型(MySQL)"""
108115

backend/core/conf.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ class Settings(BaseSettings):
4848
FASTAPI_OPENAPI_URL: str | None = '/openapi'
4949
FASTAPI_STATIC_FILES: bool = True
5050

51+
# Upload
52+
UPLOAD_READ_SIZE: int = 1024 # 上传文件时分片读取大小
53+
UPLOAD_IMAGE_EXT_INCLUDE: list[str] = ['jpg', 'jpeg', 'png', 'gif', 'webp']
54+
UPLOAD_IMAGE_SIZE_MAX: int = 1024 * 1024 * 5
55+
UPLOAD_VIDEO_EXT_INCLUDE: list[str] = ['mp4', 'mov', 'avi', 'flv']
56+
UPLOAD_VIDEO_SIZE_MAX: int = 1024 * 1024 * 20
57+
5158
# Database
5259
DATABASE_ECHO: bool = False
5360
DATABASE_SCHEMA: str = 'fba'
@@ -114,7 +121,6 @@ class Settings(BaseSettings):
114121
CORS_ALLOWED_ORIGINS: list[str] = [
115122
'http://127.0.0.1:8000',
116123
'http://localhost:5173', # 前端地址,末尾不要带 '/'
117-
'http://localhost:63342',
118124
]
119125
CORS_EXPOSE_HEADERS: list[str] = [
120126
TRACE_ID_REQUEST_HEADER_KEY,

backend/core/path_conf.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
# 离线 IP 数据库路径
1818
IP2REGION_XDB = os.path.join(BasePath, 'static', 'ip2region.xdb')
1919

20-
# 挂载静态目录
20+
# 静态资源目录
2121
STATIC_DIR = os.path.join(BasePath, 'static')
2222

23+
# 上传文件目录
24+
UPLOAD_DIR = os.path.join(BasePath, 'static', 'upload')
25+
2326
# jinja2 模版文件路径
2427
JINJA2_TEMPLATE_DIR = os.path.join(BasePath, 'templates')
2528

backend/core/registrar.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3+
import os
4+
35
from contextlib import asynccontextmanager
46

57
import socketio
@@ -9,11 +11,12 @@
911
from fastapi_limiter import FastAPILimiter
1012
from fastapi_pagination import add_pagination
1113
from starlette.middleware.authentication import AuthenticationMiddleware
14+
from starlette.staticfiles import StaticFiles
1215

1316
from backend.common.exception.exception_handler import register_exception
1417
from backend.common.log import set_customize_logfile, setup_logging
1518
from backend.core.conf import settings
16-
from backend.core.path_conf import STATIC_DIR
19+
from backend.core.path_conf import STATIC_DIR, UPLOAD_DIR
1720
from backend.database.db import create_table
1821
from backend.database.redis import redis_client
1922
from backend.middleware.jwt_auth_middleware import JwtAuthMiddleware
@@ -101,14 +104,17 @@ def register_logger() -> None:
101104

102105
def register_static_file(app: FastAPI):
103106
"""
104-
静态文件交互开发模式, 生产将自动关闭,生产必须使用 nginx 静态资源服务
107+
静态资源服务,生产应使用 nginx 代理静态资源服务
105108
106109
:param app:
107110
:return:
108111
"""
112+
# 上传静态资源
113+
if not os.path.exists(UPLOAD_DIR):
114+
os.makedirs(UPLOAD_DIR)
115+
app.mount('/static/upload', StaticFiles(directory=UPLOAD_DIR), name='upload')
116+
# 固有静态资源
109117
if settings.FASTAPI_STATIC_FILES:
110-
from fastapi.staticfiles import StaticFiles
111-
112118
app.mount('/static', StaticFiles(directory=STATIC_DIR), name='static')
113119

114120

backend/plugin/aliyun_oss/__init__.py

Lines changed: 0 additions & 2 deletions
This file was deleted.

backend/plugin/aliyun_oss/api/__init__.py

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)