You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
4.3 KiB

from fastapi import FastAPI, File, UploadFile, HTTPException, Form,Request
import paramiko
from fastapi import Depends, APIRouter, status, Query, Path, HTTPException
from internal.models import *
from internal.database import fetch_one, fetch_all, execute_query, response_success, raise_if_exists, raise_if_not_found
from dependencies import get_current_active_user
from datetime import datetime
import os
from pathlib import Path
from limiter_config import limiter
router = APIRouter(
prefix="/photos",
tags=['图片管理']
)
app = FastAPI()
# 配置远程服务器信息
REMOTE_HOST = "www.wuruilin.cn"
REMOTE_PORT = 6000 # 默认为 22
REMOTE_USERNAME = "root"
REMOTE_PASSWORD = "zl981023"
REMOTE_BASE_DIRECTORY = "/home/blog/imgs"
def file_exists(sftp, remote_file_path: str) -> bool:
"""检查远程文件是否存在"""
try:
sftp.stat(remote_file_path)
return True
except FileNotFoundError:
return False
def ensure_remote_directory(sftp, remote_directory: str):
"""确保远程目录存在"""
try:
sftp.chdir(remote_directory) # 目录存在
except IOError:
sftp.mkdir(remote_directory) # 目录不存在,创建
sftp.chdir(remote_directory)
def list_files_in_remote_directory(sftp, remote_directory):
try:
file_list = sftp.listdir(remote_directory)
return file_list
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Could not list files in remote directory: {e}")
@router.post("/uploadfile/")
@limiter.limit("10/minute")
async def upload_file(request: Request,file: UploadFile = File(...), album_key: str = Form(...), new_filename: str = None):
try:
# 获取文件扩展名
file_extension = os.path.splitext(file.filename)[1]
# 使用原文件名,如果没有提供新的文件名
if not new_filename:
new_filename = file.filename
# 保持扩展名
if not new_filename.endswith(file_extension):
new_filename += file_extension
# 根据相册的 key 生成远程文件路径
remote_directory = Path(REMOTE_BASE_DIRECTORY) / album_key
remote_file_path = remote_directory / new_filename
remote_file_path = remote_file_path.as_posix()
# 使用 Paramiko 连接远程服务器
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(REMOTE_HOST, port=REMOTE_PORT,
username=REMOTE_USERNAME, password=REMOTE_PASSWORD)
sftp = ssh.open_sftp()
# 确保远程目录存在
ensure_remote_directory(sftp, remote_directory.as_posix())
# 检查文件是否存在,如果存在,返回错误消息
if file_exists(sftp, remote_file_path):
sftp.close()
ssh.close()
raise HTTPException(
status_code=400, detail="File with the given name already exists in the album.")
# 将文件对象直接上传到远程服务器
sftp.putfo(file.file, remote_file_path)
sftp.close()
ssh.close()
return {"filename": new_filename, "message": "File uploaded successfully"}
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Could not upload file to remote server: {e}")
@router.get("/listfiles/")
@limiter.limit("10/minute")
async def list_files(request: Request,album_key: str):
try:
remote_directory = Path(REMOTE_BASE_DIRECTORY) / album_key
remote_directory = remote_directory.as_posix()
# 使用 Paramiko 连接远程服务器
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(REMOTE_HOST, port=REMOTE_PORT, username=REMOTE_USERNAME, password=REMOTE_PASSWORD)
sftp = ssh.open_sftp()
# 获取远程目录中的文件列表
file_list = list_files_in_remote_directory(sftp, remote_directory)
sftp.close()
ssh.close()
# 构造文件URL列表
file_urls = [f"{album_key}/{filename}" for filename in file_list]
return {"files": file_urls}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Could not retrieve file list: {e}")