"""v2/chunk_api.py — Приём чанков по 30KB, финализация.""" import sys, os, base64, hashlib, logging sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'site')) import db, mimeutil sys.path.insert(0, os.path.dirname(__file__)) import init as v2 from flask import Blueprint, request, jsonify bp = Blueprint("v2", __name__, url_prefix="/v2") @bp.route("/chunk", methods=["POST"]) def receive_chunk(): body = request.get_json(silent=True) or {} if not body.get("upload_id") or not body.get("data"): return jsonify({"ok": False, "error": "missing fields"}), 400 try: v2.store_chunk(body["upload_id"], int(body.get("index", 0)), body["data"]) return jsonify({"ok": True, "received": int(body.get("index", 0))}) except Exception as e: return jsonify({"ok": False, "error": str(e)}), 500 @bp.route("/finalize", methods=["POST"]) def finalize_upload(): body = request.get_json(silent=True) or {} upload_id = body.get("upload_id", "") filename = body.get("filename", "") total = int(body.get("total", 0)) checksum = body.get("checksum", "") if not all([upload_id, filename, total]): return jsonify({"ok": False, "error": "missing fields"}), 400 chunks = v2.get_chunks(upload_id) if len(chunks) != total: return jsonify({"ok": False, "error": f"expected {total}, got {len(chunks)}"}), 409 try: file_bytes = b"".join(base64.b64decode(c) for c in chunks) except Exception as e: return jsonify({"ok": False, "error": f"decode: {e}"}), 422 if checksum and hashlib.md5(file_bytes).hexdigest() != checksum: return jsonify({"ok": False, "error": "checksum mismatch"}), 422 mime = mimeutil.guess_mime(filename) or "application/octet-stream" # Сохранить в БД conn, err = db.connect() if err: return jsonify({"ok": False, "error": f"db: {err}"}), 500 try: cur = conn.cursor() cur.execute( "INSERT INTO contracts (number, client) VALUES (%s,%s) RETURNING id", ("б/н " + __import__("datetime").datetime.now().strftime("%Y%m%d-%H%M"), ""), ) cid = cur.fetchone()[0] cur.execute( "INSERT INTO documents (filename, mime_type, original_bytes, status) VALUES (%s,%s,%s,'uploaded')", (filename, mime, file_bytes), ) cur.execute("SELECT id FROM documents WHERE filename=%s ORDER BY created_at DESC LIMIT 1", (filename,)) doc_id = cur.fetchone()[0] cur.execute("INSERT INTO supplements (contract_id, document_id, type) VALUES (%s,%s,'initial')", (str(cid), str(doc_id))) conn.commit() cur.close() finally: db.put_conn(conn) v2.delete_chunks(upload_id) v2.push_finalize({"doc_id": str(doc_id), "filename": filename, "mime_type": mime}) return jsonify({"ok": True, "contract_id": str(cid), "doc_id": str(doc_id)})