# app/api/endpoints.py from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Query from fastapi.responses import StreamingResponse from typing import List import urllib.parse from app.models.schemas import FileItem, CreateFolderRequest from app.services.minio_service import minio_service from minio.error import S3Error router = APIRouter() @router.get("/files", response_model=List[FileItem]) async def list_files(path: str = "/"): try: return minio_service.list_files(path) except S3Error as e: raise HTTPException(status_code=500, detail=str(e)) # 在 app/api/endpoints.py 中修改 upload_file 接口 @router.post("/upload") async def upload_file( file: UploadFile = File(...), path: str = Form(...) ): """ path: 完整的文件路径 (例如: folder/subfolder/image.png) """ try: # 调试信息 print(f"上传文件: {file.filename}, 目标路径: {path}") # 确保路径不以 / 开头(MinIO 规范) if path.startswith('/'): path = path[1:] # 获取文件大小 # 获取文件大小 (UploadFile 的 spool_max_size 后会存入磁盘或内存) # 为了稳妥起见,移动指针到最后获取大小,再移回 file.file.seek(0, 2) size = file.file.tell() file.file.seek(0) minio_service.upload_file( file.file, path, file.content_type or "application/octet-stream", size ) return {"message": "Upload successful", "filename": file.filename, "path": path} except Exception as e: print(f"上传错误: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @router.post("/folder") async def create_folder(req: CreateFolderRequest): try: minio_service.create_folder(req.path) return {"message": "Folder created"} except S3Error as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/download") async def download_file(path: str): try: data_stream = minio_service.get_file_stream(path) filename = path.split("/")[-1] quoted_filename = urllib.parse.quote(filename) return StreamingResponse( data_stream, media_type="application/octet-stream", headers={ "Content-Disposition": f"attachment; filename*=UTF-8''{quoted_filename}" } ) except Exception as e: raise HTTPException(status_code=404, detail="File not found or error") @router.delete("/delete") async def delete_item(path: str): try: is_dir = path.endswith("/") minio_service.delete_file(path, is_dir) return {"message": "Deleted successfully"} except S3Error as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/preview") async def preview_file(path: str): try: url = minio_service.get_presigned_url(path) return {"url": url} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/storage-info") async def get_storage_info(): try: return minio_service.get_storage_info() except S3Error as e: raise HTTPException(status_code=500, detail=str(e))