Skip to content

Commit 8d4ad3a

Browse files
committed
fix: clean up temporary pdf files after response
Made-with: Cursor
1 parent 4ade3c5 commit 8d4ad3a

2 files changed

Lines changed: 48 additions & 2 deletions

File tree

apps/backend/app/routers/reports.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import tempfile
55
import pydicom
66
from fastapi import APIRouter, HTTPException, status, File, Form, UploadFile
7+
from starlette.background import BackgroundTask
78
from typing import List, Optional
89
from .data import data
910
from pyaslreport import generate_report, get_bids_metadata
@@ -129,5 +130,10 @@ async def download_pdf(report_data: dict):
129130
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
130131
HTML(string=html_content).write_pdf(tmp.name)
131132
tmp_path = tmp.name
132-
return FileResponse(tmp_path, media_type="application/pdf", filename="report.pdf")
133+
return FileResponse(
134+
tmp_path,
135+
media_type="application/pdf",
136+
filename="report.pdf",
137+
background=BackgroundTask(os.remove, tmp_path)
138+
)
133139

apps/backend/tests/test_report.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from pathlib import Path
23
import pytest
34
from fastapi.testclient import TestClient
45
from app.main import app
@@ -40,4 +41,43 @@ def test_report_pdf_endpoint():
4041
}
4142
response = client.post("/api/report/report-pdf", json=report_data)
4243
assert response.status_code == 200
43-
assert response.headers["content-type"] == "application/pdf"
44+
assert response.headers["content-type"] == "application/pdf"
45+
46+
47+
def test_report_pdf_endpoint_removes_temp_file(tmp_path, monkeypatch):
48+
temp_pdf = tmp_path / "report.pdf"
49+
50+
class DummyTempFile:
51+
def __init__(self, path: Path):
52+
self.name = str(path)
53+
self._file = path.open("wb")
54+
55+
def __enter__(self):
56+
return self
57+
58+
def __exit__(self, exc_type, exc, tb):
59+
self._file.close()
60+
61+
class FakeHTML:
62+
def __init__(self, string: str):
63+
self.string = string
64+
65+
def write_pdf(self, path: str):
66+
Path(path).write_bytes(b"%PDF-1.4 fake")
67+
68+
monkeypatch.setattr("app.routers.reports.tempfile.NamedTemporaryFile", lambda **kwargs: DummyTempFile(temp_pdf))
69+
monkeypatch.setattr("app.routers.reports.HTML", FakeHTML)
70+
71+
report_data = {
72+
"report_data": {
73+
"asl_parameters": [("param1", "value1")],
74+
"missing_parameters": [],
75+
"basic_report": "Basic report",
76+
"extended_report": "Extended report",
77+
}
78+
}
79+
80+
response = client.post("/api/report/report-pdf", json=report_data)
81+
82+
assert response.status_code == 200
83+
assert not temp_pdf.exists()

0 commit comments

Comments
 (0)