将文件写入ASP.NET中的响应后,Post Post不起作用

时间:2010-02-25 19:19:24

标签: asp.net download

我有什么?

我有一个ASP.NET页面,允许用户在单击按钮时下载文件a。用户可以从可用文件列表(RadioButtonList)中选择他想要的文件,然后单击下载按钮进行下载。 (我不应该为每个可以下载的文件提供链接 - 这是要求)。

我想要什么?

我希望用户通过选择所需的单选按钮并单击按钮逐个下载多个文件。

我面临什么问题?

我可以第一次正确下载该文件。但是,下载后,如果我选择其他文件并单击按钮进行下载,则单击该按钮的事件不会回发,并且不会下载第二个文件。

我在按钮点击事件中使用以下代码:

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    Response.Clear();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", viewXml.Length.ToString());
    Response.ContentType = "text/plain";
    Response.Write(viewXml);
    Response.End();
}

我在这里做错了吗?

同样的问题可以在IE6,IE7和Chrome中复制。我认为这个问题与浏览器无关。

6 个答案:

答案 0 :(得分:58)

我遇到了与sharepoint相同的问题。我在页面上有一个发送文件的按钮,单击按钮后,表单的其余部分没有响应。事实证明,这是一个sharepoint的事情,它将变量_spFormOnSubmitCalled设置为true以防止任何进一步的提交。当我们发送文件时,这不会刷新页面,因此我们需要手动将此变量设置为false。

在webpart上的按钮上,将OnClientClick设置为页面的javascript中的函数。

 <asp:Button ID="generateExcel" runat="server" Text="Export Excel" 
OnClick="generateExcel_Click" CssClass="rptSubmitButton"
OnClientClick="javascript:setFormSubmitToFalse()" />

然后在javascript中我有这个功能。

function setFormSubmitToFalse() {
    setTimeout(function () { _spFormOnSubmitCalled = false; }, 3000);
    return true;
}

我发现的3秒暂停是必要的,否则我在sharepoint设置它之前设置变量。这样我让sharepoint正常设置然后我把它设置回false。

答案 1 :(得分:4)

随便,你正在做什么应该工作。我过去成功地做过类似的事情,虽然我使用了转发器和LinkBut​​tons。

我唯一能看到的不同之处在于你使用的是Response.Write()而不是Response.OutputStream.Write(),并且你正在编写文本而不是二进制文件,但鉴于ContentType你指定,这应该不是问题。此外,我在发送信息之前致电Response.ClearHeaders(),之后致电Response.Flush()(在致电Response.End()之前)。

如果它会有所帮助,这里有一个适合我的消毒版本:

// called by click handler after obtaining the correct MyFileInfo class.
private void DownloadFile(MyFileInfo file) 
{
    Response.Clear();
    Response.ClearHeaders();
    Response.ContentType = "application/file";
    Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");
    Response.AddHeader("Content-Length", file.FileSize.ToString());
    Response.OutputStream.Write(file.Bytes, 0, file.Bytes.Length);
    Response.Flush();
    Response.End();        
}

您可能需要考虑以二进制方式传输文件,方法是调用System.Text.Encoding.ASCII.GetBytes(viewXml);并将结果传递给Response.OutputStream.Write()

稍微修改您的代码:

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    byte [] bytes = System.Text.Encoding.ASCII.GetBytes(viewXml); 
    // NOTE: you should use whatever encoding your XML file is set for.
    // Alternatives:
    // byte [] bytes = System.Text.Encoding.UTF7.GetBytes(viewXml);
    // byte [] bytes = System.Text.Encoding.UTF8.GetBytes(viewXml);

    Response.Clear();
    Response.ClearHeaders();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", bytes.Length.ToString());
    Response.ContentType = "application/file";
    Response.OutputStream.Write(bytes, 0, bytes.Length);
    Response.Flush();
    Response.End();
}

答案 2 :(得分:4)

在不删除Response.End的情况下执行此操作的简单方法是添加客户端j以执行页面刷新。将js添加到按钮的onclientclick属性中。

e.g。

    onclientclick="timedRefresh(2000)"

then in your html..

    <script type="text/JavaScript">
    <!--
    function timedRefresh(timeoutPeriod) {
        setTimeout("location.reload(true);",timeoutPeriod);
    }
    //   -->

答案 3 :(得分:3)

删除Response.End()并让响应在ASP.NET生态系统中自然结束。

如果这不起作用,我建议将按钮放在单独的<form>中,并将所需数据发布到单独的HTTP处理程序。设置HTTP处理程序以导出XML而不是网页。

答案 4 :(得分:3)

我有同样的问题。在aspx页面上的Button Click事件上执行简单的Response.Writer(“”)的函数从未触发过。

课堂上的方法:

public test_class()
{
    public test_class() { }

    public static void test_response_write(string test_string) 
    {
        HttpContext context = HttpContext.Current;
        context.Response.Clear();
        context.Response.Write(test_string);
        context.Response.End();                   
    }
}

ASPX页面:

protected void btn_test_Click(object sender, EventArgs e)
{
    test_class.test_response_write("testing....");
}

当我试图找到原因时,我只是在Page_Load事件上调用了相同的函数。

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        test_class.test_response_write("testing....");
    }
}

调查问题我发现该aspx页面主体的主页位于<asp:UpdatePanel>之下。

我删除了它,它在Button_Click事件上工作。我建议你也检查一下。

答案 5 :(得分:0)

查看https://multilingualdev.wordpress.com/2014/08/19/asp-net-postback-after-response-write-work-around-solution/

将文件发送到客户端并在ASP.Net中使用response.write时,开发人员在发送文件后无法执行其他任何操作。还有其他变通方法,例如添加javascript onclick函数,该函数将在客户端获取文件后调用该函数,这类似于在调用发送文件的函数时添加meta刷新(例如Response.AppendHeader(“刷新”,“ 5; URL =”和HttpContext.Current.Request.Url.AbsoluteUri))

但是这些并没有给我我想要的外观。因此,我结合使用了这些变通办法来提出此解决方案:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

checkSendFile() ‘each time page loads it will check to see if it needs to send the file

If (Not IsPostBack) Then

‘this spot is not be executed after a form submit (postback); which means you can put 

‘ the checkSendFile() in here if you want

end If

End Sub

Private Sub checkSendFile()

Dim sendFile As String = Session(“SENDFILE”) ‘ first we get the session file to see if its time 

‘ to send a file

If Not sendFile Is Nothing Then

If sendFile = “YES” Then

Session(“SENDFILE”) = “” ‘here we clear the session file so it doesn’t send again if

‘ refreshed

sendClientFile() ‘ function to send the file to client

End If

End If

End Sub

Protected Sub btnGetFile_Click(sender As Object, e As EventArgs) Handles btnGetFile.Click

‘this is where the client clicks on a button or link or something that submits the form and 

‘ request a file to be sent to them

Session(“SENDFILE”) = “YES” ‘ we set a session variable flag 

‘then we update the GUI, or run any other method that we wanted to do after client gets file

me.lblMsgToClient.text = “Thank you for downloading file.”

RefreshPage() ‘ then we refresh the page instantly (this is where post back will update values

‘ and interface, then send file)

End Sub

Private Sub RefreshPage()

‘ here we instantly add a refresh meta tag to the header with zero seconds to refresh to the

‘ same url we are currently at

Response.AppendHeader(“Refresh”, “0;URL=” & HttpContext.Current.Request.Url.AbsoluteUri)

End Sub

Private Sub sendClientFile()

‘here you will have your file and bytes to send to browser from either file system or database

‘then you can call sendToBrowser(…)

End Sub

Private Sub sendToBrowser(ByVal fileName As String, ByVal contentType As String, ByRef fileBytes As Byte())

‘this function is just the normal send file to client

Response.AddHeader(“Content-type”, contentType)
Response.AddHeader(“Content-Disposition”, “attachment; filename=” & fileName)
Response.BinaryWrite(fileBytes)
Response.Flush()
Response.End()

End Sub