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
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}")
|