v1.0.124: fix ZIP multipart — email.parser instead of buggy cgi.FieldStorage
This commit is contained in:
+15
-21
@@ -279,36 +279,30 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
def _handle_unzip_upload(self):
|
def _handle_unzip_upload(self):
|
||||||
"""Распаковать ZIP и загрузить каждый файл в Lucee. Только файлы из корня архива."""
|
"""Распаковать ZIP и загрузить каждый файл в Lucee. Только файлы из корня архива."""
|
||||||
import zipfile, io, cgi, tempfile
|
import zipfile, io
|
||||||
|
from email.parser import BytesParser
|
||||||
|
|
||||||
# CORS preflight уже обработан nginx, но на всякий случай
|
|
||||||
self._send_cors()
|
|
||||||
|
|
||||||
# Парсим multipart через cgi.FieldStorage
|
|
||||||
content_type = self.headers.get("Content-Type", "")
|
content_type = self.headers.get("Content-Type", "")
|
||||||
length = int(self.headers.get("Content-Length", 0))
|
length = int(self.headers.get("Content-Length", 0))
|
||||||
body = self.rfile.read(length)
|
body = self.rfile.read(length)
|
||||||
|
|
||||||
# Сохраняем тело во временный файл для cgi.FieldStorage
|
# Парсим multipart через email.parser
|
||||||
fp = tempfile.TemporaryFile()
|
msg = BytesParser().parsebytes(
|
||||||
fp.write(body)
|
b"Content-Type: " + content_type.encode() + b"\r\n\r\n" + body
|
||||||
fp.seek(0)
|
)
|
||||||
|
zip_data = None
|
||||||
|
if msg.is_multipart():
|
||||||
|
for part in msg.get_payload():
|
||||||
|
if part.get_filename():
|
||||||
|
zip_data = part.get_payload(decode=True)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
zip_data = body
|
||||||
|
|
||||||
env = os.environ.copy()
|
if not zip_data:
|
||||||
env["REQUEST_METHOD"] = "POST"
|
|
||||||
env["CONTENT_TYPE"] = content_type
|
|
||||||
env["CONTENT_LENGTH"] = str(length)
|
|
||||||
|
|
||||||
form = cgi.FieldStorage(fp=fp, environ=env, keep_blank_values=True)
|
|
||||||
file_item = form.getfirst("file") or form.getfirst("files")
|
|
||||||
if not file_item or not file_item.file:
|
|
||||||
self._send_error_cors(400, "no file in request")
|
self._send_error_cors(400, "no file in request")
|
||||||
fp.close()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
zip_data = file_item.file.read()
|
|
||||||
fp.close()
|
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
try:
|
try:
|
||||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
<img src="/nubes-logo.svg" alt="Nubes">
|
<img src="/nubes-logo.svg" alt="Nubes">
|
||||||
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.123 — Lucee</span></span>
|
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.124 — Lucee</span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|||||||
Reference in New Issue
Block a user