Javascript “显示”;“装载”;Flask正在准备发送文件时发出通知
我发现自己在寻找这个问题,并找到了一个解决方案,该方案在一定程度上得到了其他stackoverflow线程的帮助 背景: 我有一个flask应用程序,可以处理大型数据集(大部分都是通过Dash和Plotly完成的,我强烈推荐) 我有一个页面,用户可以请求下载数据集的特定部分。这些文件是动态生成的,有时可能很大 用户体验问题: 当用户单击请求文件下载的按钮/链接时,flask准备动态生成的文件时,页面最多可停留10秒钟,然后最终使用send_文件响应请求,并启动下载。这段等待时间让用户感到困惑,而体验将借助微调器来指示已收到请求 技术问题: 问题是,当您将浏览器窗口指向新文件url时,您将无法控制网页的显示方式。。。换句话说,启动旋转器很容易,停止旋转是关键。这个主题已经在这里的许多其他线程中讨论过,但是有一个解决方案非常突出,并且与flask send_file例程很好地集成。在确定我将在“答案”下发布的解决方案之前,我尝试了许多其他解决方案 有关问题 此实现可能对其他人有帮助,因为它特定于flask,但问题类似于此线程: 但是,解决方案主要来自以下线程:Javascript “显示”;“装载”;Flask正在准备发送文件时发出通知,javascript,python,jquery,flask,Javascript,Python,Jquery,Flask,我发现自己在寻找这个问题,并找到了一个解决方案,该方案在一定程度上得到了其他stackoverflow线程的帮助 背景: 我有一个flask应用程序,可以处理大型数据集(大部分都是通过Dash和Plotly完成的,我强烈推荐) 我有一个页面,用户可以请求下载数据集的特定部分。这些文件是动态生成的,有时可能很大 用户体验问题: 当用户单击请求文件下载的按钮/链接时,flask准备动态生成的文件时,页面最多可停留10秒钟,然后最终使用send_文件响应请求,并启动下载。这段等待时间让用户感到困惑,而
一个好处是它保留了您在flask中定义的文件的动态命名约定,方法是在响应中附加一个头。不过,总的来说,这并没有什么突破性的,只是一个更具体问题的有效解决方案。不过,这是一个烧瓶,因此肯定有一百万种其他方法可以完成。如上所述,此解决方案是许多其他线程的组合,但最坚实的灵感来自: 它做什么 允许用户与动态或静态文件下载链接/按钮交互,并在flask服务器开始生成文件并提供文件服务时提供反馈。换句话说,它在启动文件请求后显示微调器,在启动下载后隐藏微调器。此时,下载仍需运行,但大多数用户清楚浏览器如何对此提供反馈。用户从不离开请求页面,这在请求由表单动态生成的情况下非常有用(表单不会更改状态) 烧瓶侧 在网页上显示以下内容
<div class="loading_spinner"><div></div></div>
<script type="text/javascript">
function downloadReport(url) {
showspinner();
fetch(url) // for instance: /downloads/report_1/2020/2/Robert
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: '+response.status);
return;
}
var fname = response.headers.get('my_filename'); // this was necessary because the native filename key was oddly concatinated with another
// Examine the response
response.blob().then(function(blob) {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// the filename you want
a.download = fname;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
hidespinner();
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
});
}
function showspinner(){
document.getElementsByClassName("loading_spinner")[0].style.display = "block";
}
function hidespinner(){
document.getElementsByClassName("loading_spinner")[0].style.display = "none";
}
</script>
.loading_spinner {
/* display: inline-block; */
/* transform: translateZ(1px); */
position: absolute;
left:50%;
top:30%;
display:none;
}
.loading_spinner > div {
display: inline-block;
width: 64px;
height: 64px;
margin: 8px;
border-radius: 50%;
background: #25aae1;
animation: lds-circle 2.4s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}
@keyframes loading_spinner {
0%, 100% {
animation-timing-function: cubic-bezier(0.5, 0, 1, 0.5);
}
0% {
transform: rotateY(0deg);
}
50% {
transform: rotateY(1800deg);
animation-timing-function: cubic-bezier(0, 0.5, 0.5, 1);
}
100% {
transform: rotateY(3600deg);
}
}
<div class="loading_spinner"><div></div></div>