Implement reusable upload platform

This commit is contained in:
“Naeel”
2026-09-05 08:51:32 +03:00
parent 82d9ca9136
commit c0b87880ae
35 changed files with 734 additions and 9 deletions
+79
View File
@@ -0,0 +1,79 @@
"""Blueprint слоя закачки ссылок через ВМ-буфер."""
import logging
import requests
from flask import Blueprint, jsonify, request
from ..session import (MAX_FILE_BYTES, add_file, configure, create_session,
file_count, get_files)
from .config import PULL_RETRIES, PULL_RETRY_DELAY, VM_UPLOAD_PREFIX
from .pull_file import pull_file
from .safe_name import safe_name
log = logging.getLogger("upload.upload_refs")
def create_upload_refs_blueprint(cfg: dict) -> Blueprint:
"""Создать Blueprint с POST ``/upload_refs``."""
cfg = cfg or {}
prefix = cfg.get("apiPrefix", "/api")
vm_prefix = cfg.get("vmUploadUrl", VM_UPLOAD_PREFIX)
max_file_bytes = cfg.get("maxFileBytes", MAX_FILE_BYTES)
pull_retries = cfg.get("pullRetries", PULL_RETRIES)
pull_delay = cfg.get("pullRetryDelay", PULL_RETRY_DELAY)
pull_timeout = cfg.get("pullTimeout", 120)
configure(max_session_bytes=cfg.get("maxSessionBytes"))
blueprint = Blueprint("upload_refs", __name__, url_prefix=prefix)
@blueprint.route("/upload_refs", methods=["POST"])
def upload_refs():
data = request.get_json(silent=True) or {}
sid = data.get("session") or create_session()
refs = data.get("files") or []
if not isinstance(refs, list) or not refs:
return jsonify({"ok": False, "error": "No files"}), 400
added = 0
try:
with requests.Session() as client:
for ref in refs:
if not isinstance(ref, dict):
continue
name = safe_name(ref.get("name", ""))
url = ref.get("url")
if not name or not isinstance(url, str) or not url.startswith(vm_prefix):
continue
if (ref.get("size") or 0) > max_file_bytes:
_delete(client, url)
continue
content = pull_file(
client, url, max_file_bytes, pull_retries, pull_delay,
pull_timeout, sid=sid, name=name,
)
if not add_file(sid, name, content):
if get_files(sid) is None:
return jsonify({"ok": False, "error": "Session not found"}), 404
_delete(client, url)
continue
_delete(client, url)
added += 1
except Exception as error:
log.error("upload_refs: pull error sid=%s: %r", sid, error)
return jsonify({"ok": False, "error": "Pull failed: %s" % error}), 502
return jsonify({"ok": True, "session": sid, "count": file_count(sid)})
return blueprint
def _delete(client, url: str):
"""Удалить временный объект на ВМ, не ломая основной запрос при сбое."""
try:
client.delete(url, timeout=10)
except Exception:
log.warning("upload_refs: could not delete VM object url=%r", url)