简体   繁体   English

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

[英]Why won't Response.Write() export a CSV file to the browser?

I'm trying to export the contents of a DataTable to the user's browser as an Excel .csv file. 我正在尝试将DataTable的内容作为Excel .csv文件导出到用户的浏览器。 When I click the "Export" button and step through my code in the debugger, everything looks like it's happening, but no file actually gets sent to the browser. 当我单击“导出”按钮并在调试器中逐步执行我的代码时,一切看起来都在发生,但实际上没有文件被发送到浏览器。 The thing is, I'm using this EXACT SAME CODE in another project and it works there. 问题是,我在另一个项目中使用这个完全相同的代码,它在那里工作。

EDIT : Here's my ASPX markup for the entire UpdatePanel containing the button: 编辑 :这是包含按钮的整个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>

Here's the "btnExport_Click" C# function in the code behind: 这是后面代码中的“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();
}

Here's the HelperFunctions.CreateCSVFile() method: 这是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();
}

Like I said, this same code is working perfectly in another project. 就像我说的,这个相同的代码在另一个项目中完美运行。 Any ideas what might be happening? 有什么想法可能会发生什么?

EDIT : I watched the response in Fiddler, and as far as I can tell, the correct response is coming back - the browsers (Chrome, IE, Firefox) are just not responding to the file that is sent. 编辑 :我看了Fiddler的回复,据我所知,正确的回复正在回归 - 浏览器(Chrome,IE,Firefox)只是没有响应发送的文件。 Here's what the response looks like: 这是响应的样子:

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

Then there's a blank line and the file contents are dumped. 然后是一个空行,文件内容被转储。 The contents also look correct. 内容也看起来正确。 I'm baffled. 我很困惑。

The UpdatePanel is probably the problem here. UpdatePanel可能是这里的问题。 You're writing the file directly to the response, but the UpdatePanel is using Microsoft's funky AJAX voodoo, which expects its result to come back as its own special breed of HTML and data. 您正在将文件直接写入响应,但UpdatePanel正在使用Microsoft的时髦AJAX voodoo,它希望其结果可以作为自己特殊的HTML和数据返回。 I'd bet their javascript is throwing an error. 我敢打赌他们的javascript会抛出错误。

If you remove the button from the update panel, you should be ok. 如果从更新面板中删除该按钮,则应该没问题。

As @JoeEnos explained, your UpdatePanel is the culprit. 正如@JoeEnos解释的那样,你的UpdatePanel是罪魁祸首。 Make the btnNoUsageExport do a postback in your UpdatePanel's Triggers section: btnNoUsageExport在UpdatePanel的“触发器”部分中进行回发:

<asp:PostBackTrigger ControlID="btnNoUsageExport" />

This way the response will be sent to the browser instad of interpreted by MS's AJAX-script. 这样, 响应将被发送到由MS的AJAX脚本解释的浏览器 instad。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM