CSV导出Response.End异常抛出

时间:2012-07-10 21:03:49

标签: c# asp.net multithreading

我花了最近几天试图解决这个问题。我已经进行了详尽的谷歌搜索,尝试了许多解决方案,没有运气。

实质上,我正在尝试将数据导出为CSV并下载。代码有效,但抛出异常。我的特殊用法需要多次下载(如下面的示例)背靠背,但异常可以防止这种情况发生。

string attachment = string.Format("attachment; filename={0}_OutPut.csv", companyName);

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "text/csv";
HttpContext.Current.Response.AddHeader("Pragma", "public");
WriteColumnName("Column1,Column2,Column3");

StringBuilder stringBuilder = new StringBuilder();

foreach (Item i in list.Items)
{
    AddData(i.TaxCodeValue.ToString(), stringBuilder);
    AddData(i.Description.ToString(), stringBuilder);
    AddData(i.Description.ToString(), stringBuilder);

    stringBuilder.Length = 0; //Reset Stringbuilder value
    HttpContext.Current.Response.Write(stringBuilder.ToString());
    HttpContext.Current.Response.Write(Environment.NewLine);
}

HttpContext.Current.Response.End(); <---This is the problem

我读过:

http://support.microsoft.com/kb/312629

Alternative to Response.End()?

Thread was being aborted when exporting to excel?

我理解Response.End()抛出一个异常,因为它正在中止线程(通常不建议)。但是,对于我的情况,我没有看到任何替代方案。

我尝试过的一些事情:

  1. HttpContext.Current.ApplicationInstance.CompleteRequest();作为Response.End()的替代方案。这导致我的CSV充满垃圾,而不是我正在写的实际数据。
  2. HttpContext.Current.Response.Redirect("Page.aspx", false);只刷新页面,不会下载书面数据。
  3. 在catch块中捕获异常。它总是设法逃脱并且起波纹。
  4. 有什么想法吗?

    提前谢谢。

1 个答案:

答案 0 :(得分:0)

当您在此处输出文件到流时,您基本上必须“劫持”Page的正常流程。您应该使用通用处理程序(实现IHttpHandler的.ashx文件)。

实施通用处理程序时,您无需担心调用Response.ClearResponse.End,因为您将自己提供完整的响应。然后你的页面将链接到ashx处理程序,传入必要的Query String参数来加载你的数据。

示例:您的网页上有“/MyCsvDownload.ashx?CompanyID=11”

的链接

您的项目将定义一个HelperClass,声明WriteColumnHeaders和AddData静态方法,以及MyCsvDownload.ashx,代码如下:

public class MyCsvDownload : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        var companyId = int.Parse(context.Request.QueryString["CompanyID"]);

        string companyName;
        ItemList list;

        // TODO: Load company name and items from Company ID.

        string attachment = string.Format("attachment; filename={0}_OutPut.csv", companyName); 

        context.Response.AddHeader("content-disposition", attachment);
        context.Response.ContentType = "text/csv";
        context.Response.AddHeader("Pragma", "public");

        StringBuilder stringBuilder = new StringBuilder();

        HelperClass.WriteColumnName("Column1,Column2,Column3", stringBuilder);
        context.Response.Write(stringBuilder.ToString());
        context.Response.Write(Environment.NewLine);
        stringBuilder.Clear();

        foreach (Item i in list.Items)
        {
            HelperClass.AddData(i.TaxCodeValue.ToString(), stringBuilder);
            HelperClass.AddData(i.Description.ToString(), stringBuilder);
            HelperClass.AddData(i.Description.ToString(), stringBuilder);

            context.Response.Write(stringBuilder.ToString());
            context.Response.Write(Environment.NewLine);
            stringBuilder.Clear();
        }

        context.Response.Flush();
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}