I need to download files stored in MongoDB (and not in file system) using FastAPI.
I use FastAPI Response for this, because FileResponse can only be used if files are in the file system. Downloading works, but I cannot find a way to specify the filename when downloading it.
Downloading works, but filename is by default response_SOME-NUMBER.txt (from Swagger).
Here's the code.
@app.get("/files/{file_name}", responses = {200: {"content": {"text/html": {}}}}, response_class = Response)
def download_file(file_name: str):
with MongoClient() as client:
files_collection = client[DB][FILES_COLLECTION]
result = files_collection.find_one({"file_name": file_name})
content = result["file_data"]
if result is not None:
return Response(content=content, media_type="text/html")
else:
raise HTTPException(status_code=404, detail="File not found")
I guess I can add the name in the headers to be retrieved by the UI, like this:
headers = {'Content-Disposition': f'attachment; filename="{download_file_name}"'}
return Response(content=content, headers=headers, media_type="text/html")
But I would like to know if there is a way to do specify the name similarly to FileResponse.
As it has been previously described in the following answers:
How to upload a csv file using Jinja2 Templates and FastAPI , and return it after modifications?
How to return a PDF file from in-memory buffer using FastAPI?
How to return and download Excel file using FastAPI?
Download PDF file using pdfkit and FastAPI
How do I download a file from FastAPI backend using JavaScript Fetch API in the frontend?
How to generate and return a PDF file from in-memory buffer using FastAPI?
How to Download a File after POSTing data using FastAPI?
How to have the dialog box for choosing download location appeared in the frontend, before the file gets downloaded, using FastAPI?
How to display a Matplotlib chart with FastAPI/ Nextjs without saving the chart locally?
Render NumPy array in FastAPI
when returning a
Responseinstance, one could set theContent-Dispositionresponse header, indicating whether a file should be displayed inside the browser/webpage (usinginlineas the value for the first parameter in the header, which is the default) or downloaded (usingattachment), as well as specify thefilename(which is optional) when the file is downloaded to the client's device.Note that "the string following
filenameshould always be put into quotes; but, for compatibility reasons, many browsers try to parse unquoted names that contain spaces" (if thefilenamecontains unicode characters, one should instead use thefilename*parameter and encode the filename value—see this answer).Example
When returning a
FileResponse—which inherits fromResponse, as every other response class in FastAPI/Starlette—and setting thefilenameparameter, FastAPI/Starlette, behind the scenes, actually sets theContent-Dispositionheader for you. This can be seen in the implementation ofFileResponseclass here:As explained earlier, and as shown in the implementation of
FileResponseabove, Starlette will check if thefilenamevalue passed contains non-ascii/unicode characters, and if so, it will use thefilename*parameter instead and send the value encoded.Hence, in your case, you could either set the
Content-Dispositionheader on your own (which might be the most suitable solution), as demonstrated in the example earlier, or implement your own custom response class, inheriting from Starlette'sResponse, which would accept bytescontentand afilenameparameter for setting the header as inFileResponseabove.