"""Upload service — accept file, store to DB, parse.""" import uuid, base64, json from email.parser import BytesParser from db import documents, contracts, supplements from .parse import parse_file def handle_upload(rfile, content_type, content_length): """Parse multipart upload, store in DB, return result dict.""" body = rfile.read(content_length) msg = BytesParser().parsebytes( b"Content-Type: " + content_type.encode() + b"\r\n\r\n" + body ) filename = None file_data = None contract_id = "" if msg.is_multipart(): for part in msg.get_payload(): fn = part.get_filename() if fn: filename = fn file_data = part.get_payload(decode=True) else: disp = part.get("Content-Disposition", "") if 'name="contract_id"' in disp: contract_id = part.get_payload(decode=True).decode("utf-8", errors="ignore").strip() if not filename or not file_data: return {"ok": False, "error": "no file in request"} mime = _mime_for(filename) b64 = base64.b64encode(file_data).decode() # Удалить старый файл с тем же именем в этом контракте if contract_id: supplements.delete_by_document(contract_id, filename) doc = documents.insert(filename, mime, b64) # Создать контракт если нет if not contract_id: from datetime import datetime now = datetime.now() c = contracts.insert(f"б/н {now.strftime('%Y%m%d')}-{now.strftime('%H%M')}") contract_id = c["id"] supp_type = "initial" else: supp_type = "additional" supplements.insert(contract_id, doc["id"], supp_type) # Парсинг на VM parsed = parse_file(filename, file_data) if parsed and parsed.get("status") == "parsed": documents.set_parsed(doc["id"], parsed["elements"]) elif parsed and parsed.get("status") == "error": documents.set_error(doc["id"], parsed.get("error", "parse failed")) return { "ok": True, "doc_id": doc["id"], "contract_id": contract_id, "filename": filename, "size": len(file_data), "parsed": parsed, } def _mime_for(filename): ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else "" mime_map = { "pdf": "application/pdf", "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "doc": "application/msword", "zip": "application/zip", } return mime_map.get(ext, "application/octet-stream")