feat:增加上传博客图片模块

This commit is contained in:
2025-10-25 22:53:46 +08:00
parent 6512c536dc
commit f6d1096dbc
7 changed files with 89 additions and 10 deletions

View File

@@ -1,6 +1,6 @@
from typing import List from typing import List
from fastapi import APIRouter, Depends, Query, Request from fastapi import APIRouter, Depends, Query, Request, UploadFile, File
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from config.auth import verify_token from config.auth import verify_token
@@ -10,7 +10,7 @@ from schemas.blog import BlogResponse, BlogQuery, BlogCategoryResponse, BlogStat
from schemas.blog_elastic import BlogSearch from schemas.blog_elastic import BlogSearch
from schemas.pagination import PageResult from schemas.pagination import PageResult
from config.database import get_db from config.database import get_db
from service import blog_service, blog_elastic_service from service import blog_service, blog_elastic_service, file_service
router = APIRouter( router = APIRouter(
prefix="/blog", prefix="/blog",
@@ -19,6 +19,11 @@ router = APIRouter(
) )
@router.post("/file/upload", summary="上传博客图片", response_model=str)
async def sync_all_blog(md5: str, file: UploadFile = File(...)):
return await file_service.upload_file(md5, file)
@router.get("/sync", summary="同步博客到elastic", response_model=bool) @router.get("/sync", summary="同步博客到elastic", response_model=bool)
def sync_all_blog(db: Session = Depends(get_db)): def sync_all_blog(db: Session = Depends(get_db)):
return blog_elastic_service.sync_all_blog(db) return blog_elastic_service.sync_all_blog(db)
@@ -46,12 +51,14 @@ def query_blog_by_condition(query: BlogQuery = Depends(),
def query_blog_by_id(blog_id: int, db: Session = Depends(get_db)): def query_blog_by_id(blog_id: int, db: Session = Depends(get_db)):
return blog_service.query_blog_by_id(db, blog_id) return blog_service.query_blog_by_id(db, blog_id)
@router.get("/all/page", summary="分页查询博客", response_model=PageResult[BlogResponse]) @router.get("/all/page", summary="分页查询博客", response_model=PageResult[BlogResponse])
def query_blog_by_page(current_page: int = Query(1, ge=1, alias="currentPage", description="当前页码"), def query_blog_by_page(current_page: int = Query(1, ge=1, alias="currentPage", description="当前页码"),
page_size: int = Query(10, ge=1, le=100, alias="pageSize", description="每页数量"), page_size: int = Query(10, ge=1, le=100, alias="pageSize", description="每页数量"),
db: Session = Depends(get_db), _=Depends(verify_token)): db: Session = Depends(get_db), _=Depends(verify_token)):
return blog_service.query_blog_by_page(db, current_page, page_size, True) return blog_service.query_blog_by_page(db, current_page, page_size, True)
@router.post("", summary="新增博客内容", response_model=bool) @router.post("", summary="新增博客内容", response_model=bool)
def add_blog(blog: BlogCreate, db: Session = Depends(get_db), _=Depends(verify_token)): def add_blog(blog: BlogCreate, db: Session = Depends(get_db), _=Depends(verify_token)):
return blog_service.add_blog(db, blog) return blog_service.add_blog(db, blog)

15
config/rustfs.py Normal file
View File

@@ -0,0 +1,15 @@
import boto3
from botocore.client import Config
from config.setting import settings
access_key = 'jRxroVX8PUuSOia71qE4'
secret_access = 'RZE82VATN1Gqj9xy3d5OzFvHoDBgwJ4PSf7IKuei'
s3 = boto3.client('s3',
endpoint_url=f'http://{settings.RUSTFS_HOST}:{settings.RUSTFS_PORT}',
aws_access_key_id=access_key,
aws_secret_access_key=secret_access,
config=Config(signature_version='s3v4'),
region_name='cn-east-1'
)

View File

@@ -8,6 +8,8 @@ class Settings(BaseSettings):
DB_PASSWORD: str DB_PASSWORD: str
ES_HOST: str ES_HOST: str
FLUENTD_HOST: str FLUENTD_HOST: str
RUSTFS_HOST:str
RUSTFS_PORT: str
class Config: class Config:
env_file = ".env" # 指定.env文件路径 env_file = ".env" # 指定.env文件路径

View File

@@ -1 +1 @@
fastapi~=0.115.12 fastapi~=0.115.12

View File

@@ -1,6 +1,6 @@
from typing import Optional from typing import Optional
from pydantic import BaseModel, Field from pydantic import BaseModel
from datetime import datetime from datetime import datetime

View File

@@ -17,11 +17,12 @@ def sync_all_blog(db: Session) -> bool:
if settings.ENVIRONMENT == 'dev': if settings.ENVIRONMENT == 'dev':
return True return True
query = select( stmt = select(
Blog.id, Blog.id,
Blog.title, Blog.title,
BlogCategory.name.label("category"), BlogCategory.name.label("category"),
BlogContent.content.label("content"), BlogContent.content.label("content"),
Blog.is_approved.label("isApproved"),
Blog.create_time.label("createTime"), Blog.create_time.label("createTime"),
Blog.update_time.label("updateTime"), Blog.update_time.label("updateTime"),
).select_from(Blog).outerjoin( ).select_from(Blog).outerjoin(
@@ -29,7 +30,7 @@ def sync_all_blog(db: Session) -> bool:
).outerjoin( ).outerjoin(
BlogContent, Blog.content_id == BlogContent.id BlogContent, Blog.content_id == BlogContent.id
) )
results = db.execute(query).fetchall() results = db.execute(stmt).fetchall()
actions = [ actions = [
{ {
@@ -40,6 +41,7 @@ def sync_all_blog(db: Session) -> bool:
"title": blog.title, "title": blog.title,
"category": blog.category, "category": blog.category,
"content": blog.content.decode("utf-8"), "content": blog.content.decode("utf-8"),
"isApproved": blog.isApproved,
"createTime": blog.createTime.strftime("%Y-%m-%d %H:%M:%S"), "createTime": blog.createTime.strftime("%Y-%m-%d %H:%M:%S"),
"updateTime": blog.updateTime.strftime("%Y-%m-%d %H:%M:%S") "updateTime": blog.updateTime.strftime("%Y-%m-%d %H:%M:%S")
} }
@@ -106,10 +108,23 @@ def search_blog(keyword: str) -> List[BlogSearch]:
# 构造查询请求 # 构造查询请求
body = { body = {
"query": { "query": {
"multi_match": { "bool": {
"query": keyword, "must": [
"fields": ["title^3", "content"], {
"type": "phrase" "multi_match": {
"query": keyword,
"fields": ["title^3", "content"],
"type": "phrase"
}
}
],
"filter": [
{
"term": {
"isApproved": 1
}
}
]
} }
}, },
"highlight": { "highlight": {

40
service/file_service.py Normal file
View File

@@ -0,0 +1,40 @@
from fastapi import UploadFile, File, HTTPException
from config.rustfs import s3
from config.setting import settings
ALLOWED_IMAGE_TYPES = [
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/svg+xml",
]
BUCKET = 'blog'
NGINX_PROXY = 'rustfs'
async def upload_file(md5: str, file: UploadFile = File(...)) -> str:
# 校验文件类型是否是图片
if file.content_type not in ALLOWED_IMAGE_TYPES:
raise HTTPException(
status_code=400,
detail="只允许上传图片文件 (JPEG, PNG, GIF, WEBP, SVG)"
)
file_ext = file.filename.split('.')[-1]
unique_filename = f"{md5}.{file_ext}"
file_content = await file.read()
# 上传到S3
s3.put_object(
Bucket=BUCKET,
Key=unique_filename,
Body=file_content,
ContentType=file.content_type
)
# 返回文件url
return f"{NGINX_PROXY}/{BUCKET}/{unique_filename}"