python - How do I download a file from FastAPI backend using JavaScript Fetch API in the frontend? - Stack Overflow

This is my FastAPI(python) code, which returns a .ics file:@app.get("latLong")async def r

This is my FastAPI(python) code, which returns a .ics file:

@app.get("/latLong/")
async def read_item(lat: float,long:float):
    mainFunc(lat,long)
    return FileResponse("/tmp/myics.ics")

This is my frontend code in Javascript using Fetch API:

<script>
  async function apiCall(long,lat) {
    let myObject = await fetch('myapi/lat/long');
    let myText = await myObject.text();
  }
</script>

So from my visor (my api logs), it successfully calls the API. But from the front end, I am trying to get it to return the file.

The end result I would like to achieve is when the user clicks a button, the browser grabs the location, then sends the location to the API, and the API returns a file that the user can download.

This is my FastAPI(python) code, which returns a .ics file:

@app.get("/latLong/")
async def read_item(lat: float,long:float):
    mainFunc(lat,long)
    return FileResponse("/tmp/myics.ics")

This is my frontend code in Javascript using Fetch API:

<script>
  async function apiCall(long,lat) {
    let myObject = await fetch('myapi./lat/long');
    let myText = await myObject.text();
  }
</script>

So from my visor (my api logs), it successfully calls the API. But from the front end, I am trying to get it to return the file.

The end result I would like to achieve is when the user clicks a button, the browser grabs the location, then sends the location to the API, and the API returns a file that the user can download.

Share Improve this question edited Jun 17, 2023 at 5:13 Chris 35.6k10 gold badges104 silver badges251 bronze badges asked Feb 20, 2022 at 5:45 paidsponsorpaidsponsor 331 silver badge5 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 5

Server side

First, you need to adjust your endpoint on server side to accept path parameters, as in the way that is currently defined, lat and long are expected to be query parameters instead; however, in the JavaScript code you provided, it seems that 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):
    pass

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)

All together (more details and examples can be found at this answer as well):

from fastapi import FastAPI
from fastapi.responses import FileResponse


app = FastAPI()


@app.get("/{lat}/{long}/")
async def read_item(lat: float, long: float):
    headers = {'Access-Control-Expose-Headers': 'Content-Disposition'}
    return FileResponse("/tmp/myics.ics", filename="myics.ics", headers=headers)

Client side

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, es (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  
    });

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745106607a4611594.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信