簡體   English   中英

如何在前端使用 Fetch API 下載從 FastAPI 后端返回的文件?

[英]How do I download a file returned from FastAPI backend using Fetch API at the frontend?

這是我的 FastAPI(python) 代碼,它返回一個.ics文件:

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

這是我在 Javascript 中使用 Fetch API 的前端代碼:

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

所以從我的遮陽板(我的 api 日志)中,它成功地調用了 API。 但從前端,我試圖讓它返回文件。

我想要實現的最終結果是當用戶單擊按鈕時,瀏覽器抓取位置,然后將位置發送給 API,API 返回一個用戶可以下載的文件。

首先,您需要在服務器端調整您的端點以接受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")

如果您正在執行跨域請求(另請參閱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)

在客戶端,您可以對這個答案使用類似的方法(該答案建議的downloadjs庫現在已過時;因此,我不建議使用它)。 下面的示例還考慮了filename包含 unicode 字符(即-, !, (, )等)的情況,因此(utf-8 編碼)以例如filename*=utf-8''Na%C3%AFve%20file.txt的形式出現filename*=utf-8''Na%C3%AFve%20file.txt (有關詳細信息,請參見此處)。 在這種情況下, 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  
    });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM