feat: multi-file upload with zip extraction
This commit is contained in:
@@ -4,7 +4,7 @@ import os
|
||||
import tempfile
|
||||
import threading
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from typing import List, Optional
|
||||
|
||||
import httpx
|
||||
import yaml
|
||||
@@ -195,20 +195,34 @@ async def preview_file(stage: str, filename: str, lines: int = 120):
|
||||
|
||||
|
||||
@app.post("/api/upload")
|
||||
async def upload_file(file: UploadFile = File(...)):
|
||||
async def upload_files(files: List[UploadFile] = File(...)):
|
||||
_require_ssh()
|
||||
|
||||
suffix = Path(file.filename).suffix
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
|
||||
tmp.write(await file.read())
|
||||
tmp_path = tmp.name
|
||||
|
||||
try:
|
||||
remote_path = f"{STAGE_DIRS['input']}/{file.filename}"
|
||||
ssh_manager.upload_file(tmp_path, remote_path)
|
||||
return {"uploaded": file.filename, "remote_path": remote_path}
|
||||
finally:
|
||||
os.unlink(tmp_path)
|
||||
results = []
|
||||
for file in files:
|
||||
suffix = Path(file.filename).suffix.lower()
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
|
||||
tmp.write(await file.read())
|
||||
tmp_path = tmp.name
|
||||
try:
|
||||
if suffix == ".zip":
|
||||
remote_tmp = f"/tmp/{file.filename}"
|
||||
ssh_manager.upload_file(tmp_path, remote_tmp)
|
||||
input_dir = STAGE_DIRS["input"]
|
||||
out, err, code = ssh_manager.execute(
|
||||
f"unzip -o '{remote_tmp}' -d '{input_dir}' "
|
||||
f"&& rm '{remote_tmp}'",
|
||||
use_conda=False,
|
||||
)
|
||||
if code != 0:
|
||||
raise HTTPException(status_code=500, detail=f"Unzip failed for {file.filename}: {err}")
|
||||
results.append({"file": file.filename, "action": "extracted"})
|
||||
else:
|
||||
remote_path = f"{STAGE_DIRS['input']}/{file.filename}"
|
||||
ssh_manager.upload_file(tmp_path, remote_path)
|
||||
results.append({"file": file.filename, "action": "uploaded", "remote_path": remote_path})
|
||||
finally:
|
||||
os.unlink(tmp_path)
|
||||
return {"results": results}
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user