问题
这个问题困扰了我很长一段时间。我正在处理一个Web API,它提供了根据某些特定条件查询数据库的功能,获取合格数据,并生成 .xls 文件下载。
但是,数据量实际上非常大,因此生成 .xls 文件会花费相当长的时间。 这可能会导致HTTP超时。我曾经创建过一个生成器来逐行生成由 .csv 格式化的记录。然而,它在性能方面表现很好(我的意思是快速生成和下载),但有一些副作用。正如我在前两个问题中提到的那样:
How can I adapt my code to make it compatible to Microsoft Excel?
How can I send an xls file one line per time through http response?
Qeustions
经过认真考虑,我最终决定在服务器端生成整个 .xls 文件,然后提供下载。但是,如何在生成 .xls 文件的过程中维护http连接?
答案 0 :(得分:2)
"如何在生成.xls文件的过程中维护http连接?"
简单回答:你做不到。至少你不能保证单个简单的HTTP GET请求(和底层的TCP连接)可靠地工作。根据客户端的具体情况和客户端所在的网络,您的用户可能经常遇到错误(应用程序无法处理的连接超时)。
所以,正确的问题是:您需要哪种技术才能让用户获取此文件,而不管生成所需的时间以及互联网连接有多糟糕?
有许多可能的方法,所有这些方法都有其缺点。根据您要支持的浏览器,有几个选项。所有这些都需要客户端JavaScript使用。
您可能希望使用现代Server-Sent events,它允许服务器主动触发浏览器中的事件,浏览器可以根据需要对其进行响应。
更经典的方法是(长)轮询HTTPS,你可以像以前那样进行轮询,但是在客户端和服务器上配置超时时间要非常大。此外,您需要安装JavaScript,以便在超时的情况下重复请求。此外,还建立了防止超时的脏技术。
您可能希望使用术语"服务器推送","彗星","长轮询"进行一些研究。这样做,你可能会阅读WebSockets(我认为你并不直接需要)。
我想如果我是你,我现在会选择使用服务器发送的事件。但是你必须自己解决这个问题,具体取决于你的具体要求。
快速浏览一下,对本文的介绍可能是一个很好的解读:https://jersey.java.net/documentation/latest/sse.html
此外,引入W3C Server-Sent Events specification很不错。引用:
可以使用HTTP 301和307重定向事件流请求 重定向与普通HTTP请求一样。 如果是,客户将重新连接 连接已关闭;可以告诉客户停止使用重新连接 HTTP 204 No Content响应代码。
使用此API而不是使用XMLHttpRequest或者模拟它 iframe允许用户代理更好地利用网络资源 在用户代理实现者和网络运营商的情况下 能够提前协调。除了其他好处之外,还可能产生这种效果 显着节省便携式设备的电池寿命。这是 在下面关于无连接推送的部分进一步讨论。
答案 1 :(得分:2)
我同意@Jan,服务器发送事件(SSE)可能是要走的路。如果您想获得更多花哨,可以设置芹菜任务队列并侦听task_complete信号,然后通过SSE通知用户下载已准备就绪。以下是using SSE in Flask的示例。这是celery and signaling
的链接另一种方法是在初始请求中启动异步Celery任务,然后通过setInterval()
客户端的ajax请求继续检查任务是否完成。该路由只会检查MyTask.AsyncResult(task_id).state