v1.0.161: cgi.FieldStorage for UTF-8 filenames
This commit is contained in:
+19
-18
@@ -1,6 +1,5 @@
|
|||||||
"""Upload service — accept file, store to DB, parse."""
|
"""Upload service — accept file, store to DB, parse."""
|
||||||
import uuid, base64, json
|
import uuid, base64, json, io, cgi
|
||||||
from email.parser import BytesParser
|
|
||||||
from db import documents, contracts, supplements
|
from db import documents, contracts, supplements
|
||||||
from .parse import parse_file
|
from .parse import parse_file
|
||||||
|
|
||||||
@@ -9,23 +8,28 @@ def handle_upload(rfile, content_type, content_length):
|
|||||||
"""Parse multipart upload, store in DB, return result dict."""
|
"""Parse multipart upload, store in DB, return result dict."""
|
||||||
body = rfile.read(content_length)
|
body = rfile.read(content_length)
|
||||||
|
|
||||||
msg = BytesParser().parsebytes(
|
environ = {
|
||||||
b"Content-Type: " + content_type.encode() + b"\r\n\r\n" + body
|
"REQUEST_METHOD": "POST",
|
||||||
)
|
"CONTENT_TYPE": content_type,
|
||||||
|
"CONTENT_LENGTH": str(content_length),
|
||||||
|
}
|
||||||
|
fs = cgi.FieldStorage(fp=io.BytesIO(body), environ=environ, keep_blank_values=True)
|
||||||
|
|
||||||
filename = None
|
filename = None
|
||||||
file_data = None
|
file_data = None
|
||||||
contract_id = ""
|
contract_id = ""
|
||||||
|
|
||||||
if msg.is_multipart():
|
if "files" in fs:
|
||||||
for part in msg.get_payload():
|
item = fs["files"]
|
||||||
fn = part.get_filename()
|
if isinstance(item, list):
|
||||||
if fn:
|
item = item[0]
|
||||||
filename = fn
|
filename = item.filename
|
||||||
file_data = part.get_payload(decode=True)
|
file_data = item.file.read() if hasattr(item, "file") else item.value
|
||||||
else:
|
if isinstance(file_data, str):
|
||||||
disp = part.get("Content-Disposition", "")
|
file_data = file_data.encode("utf-8")
|
||||||
if 'name="contract_id"' in disp:
|
|
||||||
contract_id = part.get_payload(decode=True).decode("utf-8", errors="ignore").strip()
|
if "contract_id" in fs:
|
||||||
|
contract_id = fs.getfirst("contract_id", "")
|
||||||
|
|
||||||
if not filename or not file_data:
|
if not filename or not file_data:
|
||||||
return {"ok": False, "error": "no file in request"}
|
return {"ok": False, "error": "no file in request"}
|
||||||
@@ -33,13 +37,11 @@ def handle_upload(rfile, content_type, content_length):
|
|||||||
mime = _mime_for(filename)
|
mime = _mime_for(filename)
|
||||||
b64 = base64.b64encode(file_data).decode()
|
b64 = base64.b64encode(file_data).decode()
|
||||||
|
|
||||||
# Удалить старый файл с тем же именем в этом контракте
|
|
||||||
if contract_id:
|
if contract_id:
|
||||||
supplements.delete_by_document(contract_id, filename)
|
supplements.delete_by_document(contract_id, filename)
|
||||||
|
|
||||||
doc = documents.insert(filename, mime, b64)
|
doc = documents.insert(filename, mime, b64)
|
||||||
|
|
||||||
# Создать контракт если нет
|
|
||||||
if not contract_id:
|
if not contract_id:
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
@@ -51,7 +53,6 @@ def handle_upload(rfile, content_type, content_length):
|
|||||||
|
|
||||||
supplements.insert(contract_id, doc["id"], supp_type)
|
supplements.insert(contract_id, doc["id"], supp_type)
|
||||||
|
|
||||||
# Парсинг на VM
|
|
||||||
parsed = parse_file(filename, file_data)
|
parsed = parse_file(filename, file_data)
|
||||||
if parsed and parsed.get("status") == "parsed":
|
if parsed and parsed.get("status") == "parsed":
|
||||||
documents.set_parsed(doc["id"], parsed["elements"])
|
documents.set_parsed(doc["id"], parsed["elements"])
|
||||||
|
|||||||
Reference in New Issue
Block a user