如何使用FastAPI在下载文件之前在前端出现选择下载位置的对话框?

问题描述 投票:0回答:1

我有一个 GET 端点,它应该返回一个巨大的文件(500Mb)。 我正在使用

FileResponse
来做到这一点(为了清晰起见,简化了代码):

 async def get_file()
       headers = {"Content-Disposition": f"attachment; filename={filename}"}
       return FileResponse(file_path, headers=headers)

问题是我必须在前端等待该文件完全下载,直到显示此对话框:

然后该文件立即保存。

例如,我有一个大小为 500 MB 的文件,当我在 UI 上单击“下载”时,我必须等待一分钟或其他时间,直到显示“保存对话框”。然后,当我单击“保存”时,文件会立即保存。显然前端正在等待文件下载,我需要的是前端立即显示“保存对话框”,然后在后台开始下载。

我需要的是这样的:立即显示对话框,然后用户单击“保存”后等待下载完成。

那么我怎样才能实现这一目标呢?

javascript python html download fastapi
1个回答
0
投票

问题概述

您尚未提供有关项目客户端的任何详细信息,但客户端似乎很可能使用异步 JavaScript 请求(例如

fetch()
请求)来请求资源(文件)。如果您使用 Swagger UI 自动文档,它还会在幕后使用 Fetch API — 请参阅 这个答案

当使用

fetch()
或任何其他异步 JavaScript 库请求如此大的文件 (500 MB) 或任何资源时(如这个答案以及这个答案这个答案中所示),必须完全接收来自服务器的响应,然后才能进一步显示窗口/对话框以选择您想要下载文件的位置(请参阅之前为 Swagger UI 案例提供的链接答案)。 因此,您可以使用以下方法之一来实现预先显示用于选择下载位置的窗口/对话框,而不是使用 JavaScript 来请求资源:

解决方案

后端

设置

filename

FileResponse
参数,例如:
return FileResponse(file_path, filename="BigFile.zip")

将添加带有 
Content-Disposition

标志的

attachment
响应标头,指示应下载文件而不是在浏览器中查看文件。但是,如果您想确定这一点,您可以自己添加标头,如
here
here所示,如下所示: @app.get("/download") def download_file(): file_path = "files/BigFile.zip" headers = {'Content-Disposition': 'attachment; filename="BigFile.zip"'} return FileResponse(file_path, headers=headers)

前端

在前端,您可以简单地使用由

<a>

标签定义的超链接:

<a href="/download">Download</a>

如果后端未设置包含 
Content-Disposition

标志的

attachment
响应标头,您可以在前端的超链接中使用
download
属性,该属性“指定目标(href 中指定的文件)属性)
将在用户单击超链接时下载
”(请参阅相关的 w3schools 文章): <a href="/download" download>Download</a>

使用按钮代替超链接

如果您需要让用户单击按钮而不是超链接,您可以使用以下选项之一:

<button> <a href="/download" style="text-decoration: none; color: unset; cursor: default;" download>Download</a> </button>

<button onclick="document.getElementById('my_link').click()">Download</button> <a id="my_link" href="/download" download hidden></a>

<form method="get" action="/download"> <button type="submit">Download</button> </form>

<button type="submit" onclick="window.location.href='/download'">Download</button>

注意:

对于上面最后两个选项,请记住在服务器端设置带有 Content-Disposition 标志的

attachment
响应标头,以便下载文件而不是在浏览器中查看文件,就像您可以的那样在这些情况下,没有
<a>
超链接
download
属性。
通过 JavaScript 启动文件下载

如果您需要通过 JavaScript 函数启动/触发文件下载,您可以使用以下代码。下面的

<button>

元素是可选的;如果您不需要用户单击按钮,而是希望通过 JS 函数自动触发文件下载,您可以将其删除。

<a id="my_link" href="/download" download hidden></a>
<button onClick="downloadFile()">Download</button>
<script>
   function downloadFile() {
     document.getElementById("my_link").click()
   }
</script>

© www.soinside.com 2019 - 2024. All rights reserved.