这是我的 FastAPI(python) 代码,它返回一个 .ics
文件:
@app.get("/latLong/")
async def read_item(lat: float,long:float):
mainFunc(lat,long)
return FileResponse("/tmp/myics.ics")
这是我使用 Fetch API 编写的前端代码:
<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 返回用户可以下载的文件。
最佳答案
首先,您需要调整服务器端的端点以接受 path
参数,按照当前定义的方式,lat
和 long
预计为 query
参数代替;但是,在您提供的 JavaScript 代码中,您似乎正在尝试将这些坐标作为 path
参数发送。因此,您的端点应如下所示:
@app.get("/{lat}/{long}/")
async def read_item(lat: float, long: float):
接下来,在 FileResponse
中设置文件名
,这样它就可以包含在 Content-Disposition
中响应 header ,稍后可以在客户端检索:
return FileResponse("/tmp/myics.ics", filename="myics.ics")
如果您正在执行cross-origin请求(另请参阅 FastAPI CORS),请确保设置 Access-Control-Expose-Headers
服务器端的响应头,指示 Content-Disposition
头应该可供浏览器中运行的 JS 脚本使用;否则,客户端将无法访问文件名
。示例:
headers = {'Access-Control-Expose-Headers': 'Content-Disposition'}
return FileResponse("/tmp/myics.ics", filename="myics.ics", headers=headers)
在客户端,您可以使用类似的方法 this answer或this answer 。下面的示例还考虑了 filename
包含 unicode 字符(即 -、!、(、)
等)的情况,因此出现 (utf-8编码),例如 filename*=utf-8''Na%C3%AFve%20file.txt
的形式(有关更多详细信息,请参阅 here)。在这种情况下,decodeURIComponent()
函数用于解码文件名
。下面的工作示例:
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
});
关于javascript - 如何在前端使用 JavaScript Fetch API 从 FastAPI 后端下载文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71191662/