【问题标题】:Response.WriteFile writing the content twiceResponse.WriteFile 两次写入内容
【发布时间】:2012-06-26 18:17:52
【问题描述】:

这是我的代码..

 string attachment = "attachment; filename=Call-Details-Report-" + startDate.SelectedDate.Value.ToString("MM-dd-yyyy") + ".csv";
        Response.Clear();
        Response.ClearHeaders();
        Response.ClearContent();
        Response.AddHeader("Content-Disposition", attachment);
        Response.ContentType = "text/csv";
        Response.AddHeader("Pragma", "public");
        Response.WriteFile(downloadLocation+"\\"+fileName);
        Response.End();

我正在使用上面的代码从某个位置下载 csv 文件。但令人惊讶的是,内容被写入了两次或三次写入我下载的文件中,尽管实际上服务器上的文件并非如此。我我正在用 C# 编写我的代码。 上面这段代码在本地机器上运行良好,但问题出在生产服务器上。

这是我的完整方法

 private void DownloadReport(string query)
{
    string downloadFolderPath = "";
    string filePath = "";
    string dbAndApplicationServerStatus = ConfigurationManager.AppSettings["SameDBAndApplicationServer"] != null ? ConfigurationManager.AppSettings["SameDBAndApplicationServer"] : "1";
    if (dbAndApplicationServerStatus == "0")
    {
        Log.Write("So the DB And Application are on differrent servers,hence trying to read Download folder path on DB Server....");
        downloadFolderPath = ConfigurationManager.AppSettings["ReportDownloadLocation"] != null ? ConfigurationManager.AppSettings["ReportDownloadLocation"] : "-1";
        Log.Write("Download Path is " + downloadFolderPath);
    }
    else
    {
        Log.Write("So the DB and Application and Db are on same server......");
        downloadFolderPath = Server.MapPath("Download");
        downloadFolderPath = downloadFolderPath.Replace("\\", "//");
        if (!Directory.Exists(downloadFolderPath))
        {
            Directory.CreateDirectory(downloadFolderPath);
        }
        Log.Write("Download Path is " + downloadFolderPath);
    }
    string status="";
    StringBuilder headerQuery = new StringBuilder();
    StringBuilder rowQuery = new StringBuilder();
    StringBuilder sqlQuery = new StringBuilder();
    filePath = downloadFolderPath;
    string folderName = DateTime.Now.ToString("MM-dd-yyyy");

    string timeStamp = DateTime.Now.ToString("MM-dd-yy-HH-mm-ss");
    string fileName = "Call-Details-Report-" + startDate.SelectedDate.Value.ToString("MM-dd-yyyy") + "_" + timeStamp + ".csv";
    filePath = filePath + "/" + fileName;

    bool commaRequired = false;

    sqlQuery.Append("SELECT * INTO OUTFILE '");
    sqlQuery.Append(filePath);
    sqlQuery.Append("' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n' FROM (");
    headerQuery.Append("Select ");
    rowQuery.Append("(Select ");

    #region Creating Query
    /*Sql Query is Created  in this region*/
    #endregion



    if (!CdrSearch.WriteReportToFile(sqlQuery.ToString(),out status))
    {
        Log.Write("Failed to generate the file to download......");
        WebPagesHelper.ShowMessage(ref lblMessage, WebPagesHelper.MessageType.Message, status);
    }
    else
    {
        Log.Write("Succesfully generated file to Download");
        string downloadLocation = Server.MapPath("Download");
        if (dbAndApplicationServerStatus == "0")
        {
            WebClient webClient = new WebClient();
            string path = ConfigurationManager.AppSettings["DownloadURL"] != null ? ConfigurationManager.AppSettings["DownloadURL"].ToString() : "";

            if (!Directory.Exists(downloadLocation))
            {
                Directory.CreateDirectory(downloadLocation);
            }
            if (File.Exists(downloadLocation + "\\" + fileName))
            {
                File.Delete(downloadLocation + "\\" + fileName);
            }
            webClient.DownloadFile(path + fileName, downloadLocation + "\\" + fileName);

        }
        Log.Write("Configured Download Location on Application" + downloadLocation);
        string attachment = "attachment; filename=Call-Details-Report-" + startDate.SelectedDate.Value.ToString("MM-dd-yyyy") + ".csv";
        Response.Clear();
        Response.ClearHeaders();
        Response.ClearContent();
        Response.AddHeader("Content-Disposition", attachment);
        Response.ContentType = "text/csv";
        Response.AddHeader("Pragma", "public");

        Log.Write(downloadLocation + "\\" + fileName);

        Response.WriteFile(downloadLocation+"\\"+fileName);
        Response.SetCookie(new HttpCookie("DStatus", "Completed"));
        Response.End();
    }
}

并且上面的方法只在点击一个按钮时被直接调用一次,所以这里没有任何循环的问题。

【问题讨论】:

  • 检查是否多次调用此主体的方法。我觉得是……
  • 我认为您显示了错误的代码 sn-p。可能是在downloadLocation 中写入文件的代码有问题。
  • 我敢打赌@DarinDimitrov 是对的,问题是生成报告的任何东西都会多次将其写入文件。
  • 尝试在您的代码前加上Thread.Sleep(10000);,并在文件名中嵌入当前时间(包括秒数!)。所以如果它执行了两次,你应该会看到两个不同的文件名
  • 虽然很傻但是你确定那个按钮只被点击了一次吗?您是否有机制在下载完成之前禁用按钮?

标签: c# asp.net download response response.write


【解决方案1】:

您可以检查以下几行的含义:

webClient.DownloadFile(path + fileName, downloadLocation + "\\" + fileName); 

Response.WriteFile(downloadLocation+"\\"+fileName); 

如果他们真的在做同样的事情,请尝试注释掉其中一个。 为了安全起见,请在下载完成之前禁用该按钮。

当我尝试以下代码(甚至发布在 IIS 上)时,它只是下载一次,正如预期的那样。

 protected void Button1_Click(object sender, EventArgs e)
        {
            string attachment = "attachment; filename=Call-Details-Report-" + DateTime.Now.ToString("MM-dd-yyyy") + ".txt";
            Response.ContentType = "text/html";
            Response.AddHeader("Content-Disposition", attachment); 
            Response.AddHeader("Pragma", "public");

            Response.WriteFile(@"C:\test.txt");
            Response.SetCookie(new HttpCookie("DStatus", "Completed")); 

            Response.End();
        }

【讨论】:

  • webclient 用于将数据从数据库服务器下载到应用程序服务器,而 Response.WriteFile 用于从应用程序服务器下载到客户端机器
【解决方案2】:

显然发生了一些奇怪的事情。您说过它在开发中有效但在生产中无效 - 您是否在两个环境中使用相同的服务器配置(即您在开发中使用 1 个服务器但在生产中使用 2 个服务器?)

假设我已经理解您的代码,您可能有 3 个步骤...

  • 从 SQL 生成报告并将其写入文件
  • 如果文件存储在不同的服务器上,请将其下载到 Web 服务器
  • 上菜

所以,在更复杂的场景中(我假设 Production 是这样),您在流程的哪个步骤开始看到重复输入?在服务器上生成报告,在 Web 服务器的副本上,还是在从 Web 服务器获取报告后仅在客户端中?

我看不出有任何理由说明您将文件提供给客户端的代码会复制数据,因此只能假设它在某个时间点之前发生过。

如果你能使用 Firebug/Fiddler/ 会很有帮助???发布从网络服务器到客户端的传输的确切内容

(顺便说一句,您可能希望查看 System.IO.Path 类来操作路径,它使您的代码更具可读性和健壮性 - 不再担心尾部斜杠!)

【讨论】:

  • 很好的数据复制在第三步......我认为罪魁祸首是 Response.WriteFile 因为我的文件很大......我正在使用 Response.TransmitFile 进行测试prod....将继续发布
  • @jade 您是否考虑过打开 Step Into .Net Framework 源代码并查看它在 Response.WriteFile(); 中的作用?
  • 我猜它是一个库,我该如何进入 Response.WriteFile??
  • 工具->选项->调试->常规。勾选Enable .NET Framework source stepping。如果您尚未设置符号,则需要设置符号。
【解决方案3】:

好的,所以在这种情况下真正的罪魁祸首是 Response.WriteFile。在我的情况下,我猜是因为数据的大小非常大,Response.WriteFile 没有按预期工作。我发现了一些在大文件下载的情况下,最好在没有其他选项的情况下使用 Response.TransmitFile.Left 我更改了代码并使用了 Response.TransmitFile 和尤里卡!问题已解决。下载的文件中不再有重复记录。虽然原因仍然未知,但 Response.TransmitFile 解决了问题.....

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 1970-01-01
    相关资源
    最近更新 更多