[英]How to let a ASP.NET page know when a file is ready for download from the server
我正在維護一個舊的 VB.Net Webforms 應用程序,添加一個部分后我遇到了一個奇怪的問題。
這是 aspx 頁面中的這段代碼,它在回發時顯示 giphy.gif:
<style type="text/css">
.modalWait
{
position: fixed;
top: 0;
left: 0;
background-color: black;
z-index: 99;
opacity: 0.5;
filter: alpha(opacity=80);
-moz-opacity: 0.8;
min-height: 100%;
width: 100%;
}
.loading
{
font-family: Arial;
font-size: 10pt;
/*border: 5px solid #67CFF5;*/
width: 100px;
height: 100px;
display: none;
position: fixed;
background-color: transparent;
z-index: 999;
}
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
function ShowProgress() {
setTimeout(function () {
var modal = $('<div />');
modal.addClass("modalWait");
$('body').append(modal);
var loading = $(".loading");
loading.show();
var top = Math.max($(window).height() / 2 - loading[0].offsetHeight / 2, 0);
var left = Math.max($(window).width() / 2 - loading[0].offsetWidth / 2, 0);
loading.css({ top: top, left: left });
}, 200);
}
$('form').live("submit", function () {
ShowProgress();
});
</script>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<form runat="server">
<asp:ScriptManager runat="server"></asp:ScriptManager>
<!-- Page Wrapper -->
<div id="wrapper">
<!-- More Code -->
</div>
<!-- End of Page Wrapper -->
<div class="loading" align="center">
<%--Loading. Please wait.<br /><br />--%>
<img src="../img/giphy.gif" />
</div>
</form>
並且對於填充控件的所有查詢都非常有效 - the.gif 在調用數據庫時出現然后消失。
但后來我添加了一個 function 來將數據網格讀入 a.csv 然后下載。 它工作得很好,除非我在后面的代碼中添加這部分:
Dim bytes As Byte() = Encoding.ASCII.GetBytes(sb.ToString())
Response.Clear()
Response.ContentType = "text/csv"
Response.AddHeader("Content-Length", bytes.Length.ToString())
Response.AddHeader("Content-disposition", "attachment; filename=contacts.csv")
Response.Write(sb.ToString())
Response.Flush()
Response.End()
該文件下載完美......但 giphy.gif 仍然存在......即使回發完成,它也不會 go 消失。
我究竟做錯了什么?
正如 VDWWD 解釋的那樣( “UI 永遠不會更新,因為服務器一次只能發送一種類型的響應(文件或 html 頁面)” )您真正的問題是您不知道文件下載何時完成(或確切地說,當准備文件的服務器端代碼完成執行時)。
SO上有很多關於這個的問題,令人驚訝的是,答案幾乎總是你不知道!
好吧,不完全是!
您始終可以通過發回包含時間戳的唯一命名 cookie 來讓客戶端知道。 在客戶端上,javascript 代碼嘗試檢測 cookie 的存在,當它檢測到時,它會隱藏您顯示的任何加載圖像(或文本或其他內容)。
所以,不用多說這里的代碼(我只使用loading
css class 使示例更簡單和更小):
<form id="form1" runat="server">
<div class="loading">
Loading. Please wait.<br />
<br />
</div>
<asp:HiddenField ID="windowid" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Download"
OnClick="Button1_Click"
OnClientClick="ShowProgress();" />
</form>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script type="text/javascript">
function ShowProgress() {
$(".loading").show();
checkCookie();
}
function checkCookie() {
var cookieVal = $.cookie($('#<%= windowid.ClientID %>').val());
if (cookieVal == null || cookieVal === 'undefined') {
setTimeout("checkCookie();", 1000);
}
else {
$(".loading").hide();
}
}
</script>
代碼隱藏 VB.NET :
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
' the hidden value will be used to uniquely name the cookie and
' will be used both on the server and the client side to
' work with the cookie.
windowid.Value = Guid.NewGuid().ToString()
End If
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs)
' for demo purposes only
System.Threading.Thread.Sleep(4000)
GetCsv()
End Sub
Protected Sub GetCsv()
' ...
Dim bytes As Byte() = Encoding.ASCII.GetBytes(sb.ToString())
Response.Clear()
Response.Cookies.Add(New HttpCookie(windowid.Value, DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:ff")))
Response.AddHeader("Content-Disposition", "attachment; filename=contacts.csv")
Response.AddHeader("Content-Length", bytes.Length.ToString())
Response.ContentType = "text/csv"
Response.Write(sb.ToString())
Response.Flush()
Response.End()
End Sub
代碼隱藏 C# :
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// the hidden value will be used to uniquely name the cookie and
// will be used both on the server and the client side to
// work with the cookie.
windowid.Value = Guid.NewGuid().ToString();
}
}
public void GetCsv()
{
// ...
var bytes = Encoding.ASCII.GetBytes(sb.ToString());
Response.Clear();
Response.Cookies.Add(new HttpCookie(windowid.Value, DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:ff")));
Response.AddHeader("Content-Disposition", "attachment; filename=contacts.csv");
Response.AddHeader("Content-Length", bytes.Length.ToString());
Response.ContentType = "text/csv";
Response.Write(sb.ToString());
Response.Flush();
Response.End();
}
protected void Button1_Click(object sender, EventArgs e)
{
// for demo purposes only
System.Threading.Thread.Sleep(2000);
GetCsv();
}
我希望這有幫助。 如果是這樣,我建議我們編輯問題的標題(可能還有一些內容),以幫助其他人最終找到一個有效的解決方案來解決一直沒有真正得到解答的問題。
您正在使用沒有 UpdatePanel 的 ScriptManager 嘗試將 (Where start <ScriptManager
........) 替換為:
<asp:ScriptManager ID="ScriptManager1" runat="server"/>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<!-- Page Wrapper -->
<div id="wrapper">
<!-- More Code -->
</div>
<!-- End of Page Wrapper -->
<div class="loading" style="text-align:center">
<%--Loading. Please wait.<br /><br />--%>
<img src="../img/giphy.gif" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
您正在下載一個文件( contacts.csv
),UI 永遠不會更新,因為服務器一次只能發送一種類型的響應(文件或 html 頁面),因此下載后圖像將保持可見。
要解決此問題,請在新瀏覽器 window 中打開下載。
<a href="/DownloadFile.aspx" target="_blank">Download CSV</a>
<a href="/handler1.ashx?file=45" target="_blank">Download CSV</a>
如果下載必須在 PostBack 之后進行,則上述解決方案將不起作用。 一個可能的解決方案是在文件的平均下載時間之后隱藏圖像。
function ShowProgress() {
//rest of code
setTimeout(function () {
loading.hide();
}, 2000);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.