c# - 为什么 Response.Write() 不会将 CSV 文件导出到浏览器?

标签 c# asp.net csv

我正在尝试将 DataTable 的内容作为 Excel .csv 文件导出到用户的浏览器。当我单击“导出”按钮并在调试器中逐步执行我的代码时,一切看起来都在发生,但实际上没有文件发送到浏览器。问题是,我在另一个项目中使用了这个完全相同的代码,并且它在那里工作。

编辑:这是我对包含该按钮的整个 UpdatePanel 的 ASPX 标记:

<asp:UpdatePanel ID="updNoUsage" runat="server">
  <ContentTemplate>
    <asp:Button ID="btnNoUsageLookup" runat="server" Text="Get No Usage Lines Report"
      OnClick="btnNoUsageLookup_Click" /><br /><br />
    <asp:Label ID="lblNoUsageMessage" runat="server" Font-Bold="True" ForeColor="Blue"
      Text="Message" Visible="False"></asp:Label><br /><br />
    <asp:Panel ID="pnlNoUsageReport" runat="server" Visible="False" BorderStyle="None">
      <asp:GridView ID="gvNoUsage" runat="server" AllowPaging="True" AllowSorting="True"
        AutoGenerateColumns="False" BorderColor="#666666" BorderStyle="Solid"
        BorderWidth="1px" PageSize="25" OnPageIndexChanging="gv_PageIndexChanging"
        OnSorting="gv_Sorting" OnRowCreated="gvNoUsage_RowCreated">
          <HeaderStyle BackColor="Transparent" />
          <RowStyle BackColor="#e5e5e5" />
          <AlternatingRowStyle BackColor="White" />
          <Columns>
            <asp:BoundField DataField="CostCenter" HeaderText="Cost Center" SortExpression="CostCenter" />
            <asp:BoundField DataField="WirelessNumber" HeaderText="Wireless Number" SortExpression="WirelessNumber" />
            <asp:BoundField DataField="ESN" HeaderText="ESN" SortExpression="ESN" />
            <asp:BoundField DataField="UserName" HeaderText="User Name" SortExpression="UserName" />
            <asp:BoundField DataField="Model" HeaderText="Handset Model" SortExpression="Model" />
          </Columns>
        </asp:GridView>
        <ajaxToolkit:AnimationExtender ID="aeNoUsage" runat="server" 
          TargetControlID="gvNoUsage">
          <Animations>
            <OnLoad>
              <Sequence>
        <FadeIn AnimationTarget="gvNoUsage" Duration=".25" />
          </Sequence>
            </OnLoad>
          </Animations>
        </ajaxToolkit:AnimationExtender>
        <br /><br />
        <asp:Button ID="btnNoUsageExport" runat="server" CausesValidation="false" 
          Text="Export to Excel" OnClick="btnExport_Click" />
      </asp:Panel>
    </ContentTemplate>
    <Triggers>
      <asp:AsyncPostBackTrigger ControlID="btnNoUsageLookup" EventName="Click" />
      <asp:AsyncPostBackTrigger ControlID="btnNoUsageExport" EventName="Click" />
    </Triggers>
  </asp:UpdatePanel>

这是后面代码中的“btnExport_Click”C# 函数:

protected void btnExport_Click(object sender, EventArgs e)
{
  //Get dataset and output filename
  DataTable dt = dtNoUsage;
  string exportFile = "No Usage Report.csv";

  //Now convert DataSet to a CSV file
  //  Clear the response so there is nothing coming back.
  Response.Clear();
  Response.ClearHeaders();

  //  Add an HTTP header for the content type to tell the browser that this is a file that is being passed back.
  Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", exportFile));

  //  Tell the browser the correct file type (should cause the file to open with Microsoft Excel)
  Response.ContentType = "application/vnd.ms-excel";

  //  Get CSV file from DataTable
  string csvData = HelperFunctions.CreateCSVFile(dt);

  //  Write the response to the HTTP stream back to the client browser
  Response.Write(csvData);

  //  End the stream write and commit it
  Response.End();
}

这是 HelperFunctions.CreateCSVFile() 方法:

public static string CreateCSVFile(DataTable dt)
{
  //  Build the file line by line from the DataSet
  StringBuilder sbFile = new StringBuilder();

  //  Add the header row
  for (int i = 0; i < dt.Columns.Count; i++)
  {
    sbFile.AppendFormat("{0}", EscapeCSVField(dt.Columns[i].ColumnName));
    if (i < dt.Columns.Count - 1)
    {
      sbFile.Append(",");
    }
  }
  //  Add a newline
  sbFile.AppendLine(String.Empty);
  //  Add the data rows
  for (int i = 1; i < dt.Rows.Count; i++)
  {
    for (int j = 0; j < dt.Columns.Count; j++)
    {
      sbFile.AppendFormat("{0}", EscapeCSVField(dt.Rows[i][j].ToString().Trim()));
      if (j < dt.Columns.Count - 1)
      {
        sbFile.Append(",");
      }
    }
    //  Add a newline
    sbFile.AppendLine(String.Empty);
  }
  return sbFile.ToString();
}

正如我所说,同样的代码在另一个项目中运行良好。知道会发生什么吗?

编辑:我在 Fiddler 中观察了响应,据我所知,正确的响应正在返回 - 浏览器(Chrome、IE、Firefox)只是没有响应文件即已发送。响应如下所示:

HTTP/1.1 200 OK
Cache-Control: public
Content-Type: application/vnd.ms-excel; charset=utf-8
Server: Microsoft-IIS/8.0
Content-Disposition: attachment; filename=Upgrade Eligibility Report.csv
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcdGltb3RoeWJcZG9jdW1lbnRzXHZpc3VhbCBzdHVkaW8gMjAxMlxQcm9qZWN0c1xXaXJlbGVzc0JpbGxpbmdWMlxXaXJlbGVzc0JpbGxpbmdWMlxVc2VyXFdpcmVsZXNzQmlsbGluZy5hc3B4?=
X-Powered-By: ASP.NET
Date: Tue, 29 Oct 2013 15:19:43 GMT
Content-Length: 16310

然后有一个空行,文件内容被转储。内容看起来也正确。我很困惑。

最佳答案

UpdatePanel 可能是这里的问题。您正在将文件直接写入响应,但 UpdatePanel 使用的是 Microsoft 时髦的 AJAX 巫术,它期望其结果作为其自己的特殊 HTML 和数据品种返回。我敢打赌他们的 javascript 会抛出错误。

如果您从更新面板中删除按钮,您应该没问题。

关于c# - 为什么 Response.Write() 不会将 CSV 文件导出到浏览器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19645651/

相关文章:

c# - 无法删除文件IO异常:

Python附加到没有白行且没有重复列的csv文件

excel - 将 CSV 导入 Excel : import wizard fails to recognize text qualifier but opening directly in Excel converts to scientific notation

c# - 到 UI 的 MVVM 通知

c# - 无法在 Visual Studio 2013 中更改项目的默认命名空间

c# - 使用 Angular/C# 上传文件

c# - 在基本 Controller 上使用 WebApi RoutePrefix 属性

javascript - 清空事件下拉列表不起作用

mysql - 检查 csv 文件中是否存在数据库记录

c# - 如何在 WPF 中向自定义控件添加滚动条?