跨服务器传文件,一台起 HTTP 服务提供下载(Server),另一台作为客户端拉取(Client)。
适用场景:大文件传输
Server 端(被下载方)
# server_a.py |
from fastapi import FastAPI, HTTPException |
from fastapi.responses import FileResponse |
import os |
app = FastAPI() |
# 文件存放目录(可通过 docker -v 挂载,或直接设为 /path/to/your/files) |
FILE_DIR = "/app/data" |
@app.get("/download/{filename}") |
def download_file(filename: str): |
file_path = os.path.join(FILE_DIR, filename) |
# 安全检查:防止路径穿越攻击(如 ../../etc/passwd) |
if not os.path.abspath(file_path).startswith(os.path.abspath(FILE_DIR)): |
raise HTTPException(status_code=400, detail="Invalid filename") |
if not os.path.exists(file_path) or not os.path.isfile(file_path): |
raise HTTPException(status_code=404, detail="File not found") |
return FileResponse(file_path, filename=filename, media_type='application/octet-stream') |
if __name__ == "__main__": |
import uvicorn |
uvicorn.run(app, host="0.0.0.0", port=7011) |
# 启动 Server(需安装 fastapi, uvicorn) |
python3 server_a.py |
Client 端(下载方)
# client_b.py |
import requests |
import os |
# 替换为 Server 的 IP 和端口 |
SERVER_A_IP = '132.0.0.1' |
PORT = "7011" |
FILENAME = "要下载的文件名" |
url = f"http://{SERVER_A_IP}:{PORT}/download/{FILENAME}" |
save_path = f"./{FILENAME}" |
print(f"开始从 {url} 下载文件...") |
try: |
with requests.get(url, stream=True, timeout=3600) as response: |
response.raise_for_status() |
total_size = int(response.headers.get('content-length', 0)) |
downloaded_size = 0 |
with open(save_path, 'wb') as f: |
for chunk in response.iter_content(chunk_size=8192): |
if chunk: |
f.write(chunk) |
downloaded_size += len(chunk) |
if total_size > 0: |
percent = (downloaded_size / total_size) * 100 |
print(f"\r下载进度: {percent:.2f}%", end="") |
print(f"\n下载完成!文件已保存至: {os.path.abspath(save_path)}") |
except requests.exceptions.RequestException as e: |
print(f"下载失败: {e}") |
# 启动 Client(需安装 requests) |
python3 client_b.py |
注意事项
- Server 和 Client 之间网络需互通(同一内网或公网可达)
- 用 Docker 跑 Server可通过
-p 7011:7011,将容器端口绑定到物理机端口,外部可通过物理机IP:端口访问容器服务,文件目录用-v挂载即可
方案二:scp(简单快捷,适合小文件)
双方必须都有 SSH 访问权限。
# 从本地推送到远程 |
scp /path/to/local/file user@remote_ip:/path/to/remote/ |
# 从远程拉取到本地 |
scp user@remote_ip:/path/to/remote/file /path/to/local/ |
# 递归传输目录 |
scp -r /path/to/local/dir user@remote_ip:/path/to/remote/ |