【问题标题】:How do I download a file from FastAPI backend using Fetch API in the frontend?如何在前端使用 Fetch API 下载从 FastAPI 后端返回的文件?
【发布时间】:2022-07-24 20:29:35
【问题描述】:

这是我的 FastAPI(python) 代码,它返回一个 .ics 文件:

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

这是我使用 Fetch API 编写的 Javascript 前端代码:

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

所以从我的 visor(我的 api 日志)中,它成功调用了 API。但从前端,我试图让它返回文件。

我想要实现的最终结果是当用户点击一个按钮时,浏览器抓取位置,然后将位置发送给API,API返回一个用户可以下载的文件。

【问题讨论】:

    标签: javascript python html fastapi


    【解决方案1】:

    首先,您需要在服务器端调整您的端点以接受path 参数,如当前定义的那样,latlong 预计为query 参数;但是,在您的 javascript 代码中,您尝试将这些坐标作为 path 参数发送。因此,您的端点应如下所示:

    @app.get("/{lat}/{long}/")
    async def read_item(lat: float, long: float):
    

    接下来,在FileResponse 中设置filename,这样它就可以包含在响应Content-Disposition 标头中,以后可以在客户端检索:

    return FileResponse("/tmp/myics.ics", filename="myics.ics")
    

    如果您正在执行cross-domain 请求(另请参阅FastAPI CORS),请确保将Access-Control-Expose-Headers:Content-Disposition 添加到服务器端的响应标头(以公开Content-Disposition 标头),否则filename 获胜'不能在客户端访问:

    headers = {'Access-Control-Expose-Headers': 'Content-Disposition'}
    return FileResponse("/tmp/myics.ics", filename="myics.ics", headers=headers)
    

    在客户端,您可以使用与this answer 类似的方法(该答案建议的downloadjs 库现在已过时;因此,我不建议使用它)。下面的示例还考虑了 filename 包含 unicode 字符(即 -, !, (, ) 等)并因此以 filename*=utf-8''Na%C3%AFve%20file.txt 的形式出现(utf-8 编码)的情况(参见 @ 987654329@了解更多详情)。在这种情况下,decodeURIComponent() 函数用于解码filename。下面的工作示例:

    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, otherwise it won't work in Firefox
            a.click();
            a.remove(); // afterwards, remove the element  
        });
    

    【讨论】:

      猜你喜欢
      • 2022-11-20
      • 1970-01-01
      • 2021-10-02
      • 2021-08-31
      • 2018-09-05
      • 2018-07-06
      • 2022-01-21
      • 1970-01-01
      • 2019-03-10
      相关资源
      最近更新 更多