I am building a FastAPI application and need to implement an endpoint that allows users to download an Excel file using streaming. The goal is for the file to start downloading immediately when the user clicks a download button in their browser, similar to how files are downloaded from websites.
Here is my current implementation:
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import openpyxl
import io
import time
app = FastAPI()
@app.get("/download_excel/")
async def get_attendance_report():
start_time = time.time()
# Create Excel file in memory
wb = openpyxl.Workbook()
ws = wb.active
headers = ["id", "name", "age", "city", "is_student"]
ws.append(headers)
# Sample data
data = [
{'id': 1, 'name': 'Alice', 'age': 30, 'city': 'New York', 'is_student': True},
{'id': 2, 'name': 'Bob', 'age': 25, 'city': 'Los Angeles', 'is_student': False}
]
for record in data:
ws.append([record['id'], record['name'], record['age'], record['city'], record['is_student']])
log.info(f"File generation time: {time.time() - start_time} seconds")
def iterfile():
with io.BytesIO() as byte_stream:
wb.save(byte_stream)
byte_stream.seek(0)
while chunk := byte_stream.read(262144): # 256KB chunks
yield chunk
headers = {
'Content-Disposition': 'attachment; filename="employee_attendance_report.xlsx"',
'Transfer-Encoding': 'chunked'
}
return StreamingResponse(iterfile(), media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', headers=headers)
Problem:
1.When I click the download button, I receive a status code 200 immediately, but it takes more time for the download process to start.
2.I want the file to be downloaded immediately when the user clicks the download button. The file should appear in the browser’s download manager, showing its name and progress.
What I’ve Tried:
Implemented StreamingResponse to stream the file in chunks.
Set the Content-Disposition header to indicate an attachment and filename.
Questions:
Is the StreamingResponse implementation correct for streaming an Excel file?
Are there any additional headers or configurations required to ensure that the file starts downloading immediately in the browser?
How can I reduce the delay between receiving the status code and the start of the download process?