Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -512,6 +512,91 @@ def process_reports():
|
|
| 512 |
logger.exception("Node pipeline failed")
|
| 513 |
return jsonify({"error": "Node pipeline failed", "detail": str(e)}), 500
|
| 514 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 515 |
@app.route("/ping", methods=["GET"])
|
| 516 |
def ping():
|
| 517 |
return jsonify({"status": "ok"})
|
|
|
|
| 512 |
logger.exception("Node pipeline failed")
|
| 513 |
return jsonify({"error": "Node pipeline failed", "detail": str(e)}), 500
|
| 514 |
|
| 515 |
+
@app.route("/upload_reports", methods=["POST"])
|
| 516 |
+
def upload_reports():
|
| 517 |
+
"""
|
| 518 |
+
Upload one or more files for a patient.
|
| 519 |
+
|
| 520 |
+
Expects multipart/form-data with:
|
| 521 |
+
- patient_id (form field)
|
| 522 |
+
- files (one or multiple files; use the same field name 'files' for each file)
|
| 523 |
+
|
| 524 |
+
Example curl:
|
| 525 |
+
curl -X POST http://localhost:7860/upload_reports \
|
| 526 |
+
-F "patient_id=12345" \
|
| 527 |
+
-F "files[]=@/path/to/report1.pdf" \
|
| 528 |
+
-F "files[]=@/path/to/report2.pdf"
|
| 529 |
+
"""
|
| 530 |
+
try:
|
| 531 |
+
# patient id can be in form or args (for convenience)
|
| 532 |
+
patient_id = request.form.get("patient_id") or request.args.get("patient_id")
|
| 533 |
+
if not patient_id:
|
| 534 |
+
return jsonify({"error": "patient_id form field required"}), 400
|
| 535 |
+
|
| 536 |
+
# get uploaded files (support both files and files[] naming)
|
| 537 |
+
uploaded_files = request.files.getlist("files")
|
| 538 |
+
if not uploaded_files:
|
| 539 |
+
# fallback: single file under name 'file'
|
| 540 |
+
single = request.files.get("file")
|
| 541 |
+
if single:
|
| 542 |
+
uploaded_files = [single]
|
| 543 |
+
|
| 544 |
+
if not uploaded_files:
|
| 545 |
+
return jsonify({"error": "no files uploaded (use form field 'files')"}), 400
|
| 546 |
+
|
| 547 |
+
# create patient folder under REPORTS_ROOT/<patient_id>
|
| 548 |
+
patient_folder = REPORTS_ROOT / str(patient_id)
|
| 549 |
+
patient_folder.mkdir(parents=True, exist_ok=True)
|
| 550 |
+
|
| 551 |
+
saved = []
|
| 552 |
+
skipped = []
|
| 553 |
+
|
| 554 |
+
for file_storage in uploaded_files:
|
| 555 |
+
orig_name = getattr(file_storage, "filename", "") or ""
|
| 556 |
+
filename = secure_filename(orig_name)
|
| 557 |
+
if not filename:
|
| 558 |
+
skipped.append({"filename": orig_name, "reason": "invalid filename"})
|
| 559 |
+
continue
|
| 560 |
+
|
| 561 |
+
# extension check
|
| 562 |
+
ext = filename.rsplit(".", 1)[1].lower() if "." in filename else ""
|
| 563 |
+
if ext not in ALLOWED_EXTENSIONS:
|
| 564 |
+
skipped.append({"filename": filename, "reason": f"extension '{ext}' not allowed"})
|
| 565 |
+
continue
|
| 566 |
+
|
| 567 |
+
# avoid overwriting: if collision, add numeric suffix
|
| 568 |
+
dest = patient_folder / filename
|
| 569 |
+
if dest.exists():
|
| 570 |
+
base, dot, extension = filename.rpartition(".")
|
| 571 |
+
# if no base (e.g. ".bashrc") fallback
|
| 572 |
+
base = base or filename
|
| 573 |
+
i = 1
|
| 574 |
+
while True:
|
| 575 |
+
candidate = f"{base}__{i}.{extension}" if extension else f"{base}__{i}"
|
| 576 |
+
dest = patient_folder / candidate
|
| 577 |
+
if not dest.exists():
|
| 578 |
+
filename = candidate
|
| 579 |
+
break
|
| 580 |
+
i += 1
|
| 581 |
+
|
| 582 |
+
try:
|
| 583 |
+
file_storage.save(str(dest))
|
| 584 |
+
saved.append(filename)
|
| 585 |
+
except Exception as e:
|
| 586 |
+
logger.exception("Failed to save uploaded file %s: %s", filename, e)
|
| 587 |
+
skipped.append({"filename": filename, "reason": f"save failed: {e}"})
|
| 588 |
+
|
| 589 |
+
return jsonify({
|
| 590 |
+
"patient_id": str(patient_id),
|
| 591 |
+
"saved": saved,
|
| 592 |
+
"skipped": skipped,
|
| 593 |
+
"patient_folder": str(patient_folder)
|
| 594 |
+
}), 200
|
| 595 |
+
|
| 596 |
+
except Exception as exc:
|
| 597 |
+
logger.exception("Upload failed: %s", exc)
|
| 598 |
+
return jsonify({"error": "upload failed", "detail": str(exc)}), 500
|
| 599 |
+
|
| 600 |
@app.route("/ping", methods=["GET"])
|
| 601 |
def ping():
|
| 602 |
return jsonify({"status": "ok"})
|