First, you need to adjust your endpoint on server side to accept path
parameters, as in the way it is currently defined, lat
and long
are expected to be query
parameters; however, in your javascript code you are trying to send those coordinates as path
parameters. Thus, your endpoint should look like this:
@app.get("/{lat}/{long}/")
async def read_item(lat: float, long: float):
Next, set the filename
in FileResponse
, so that it can be included in the Content-Disposition
response header, which can later be retrieved on client side:
return FileResponse("/tmp/myics.ics", filename="myics.ics")
If you are doing a cross-origin request (see FastAPI CORS as well), make sure to set the Access-Control-Expose-Headers
response header on server side, indicating that the Content-Disposition
header should be made available to JS scripts running in the browser; otherwise, the filename
won’t be accessible on client side. Example:
headers = {'Access-Control-Expose-Headers': 'Content-Disposition'}
return FileResponse("/tmp/myics.ics", filename="myics.ics", headers=headers)
On client side, you could use a similar approach to this answer or this answer. The below example also takes into account scenarios where the filename
includes unicode characters (i.e., -, !, (, )
, etc.) and hence, comes (utf-8 encoded) in the form of, for instance, filename*=utf-8''Na%C3%AFve%20file.txt
(see here for more details). In such cases, the decodeURIComponent()
function is used to decode the filename
. Working example below:
const url="http://127.0.0.1:8000/41.64007/-47.285156"
fetch(url)
.then(res => {
const disposition = res.headers.get('Content-Disposition');
filename = disposition.split(/;(.+)/)[1].split(/=(.+)/)[1];
if (filename.toLowerCase().startsWith("utf-8''"))
filename = decodeURIComponent(filename.replace("utf-8''", ''));
else
filename = filename.replace(/['"]/g, '');
return res.blob();
})
.then(blob => {
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a); // append the element to the dom
a.click();
a.remove(); // afterwards, remove the element
});