Response.WriteFile 写入内容两次

4

这是我的代码...

 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();
    }
}

以上方法只在单击按钮时直接调用一次,因此这里没有任何循环的问题。


3
检查此方法体是否被调用了多次。我认为是这样的... - Tomas Voracek
5
我认为你展示的代码片段是错误的。可能有问题的是写入downloadLocation文件的代码。 - Darin Dimitrov
1
我敢打赌@DarinDimitrov是对的,问题在于生成报告的任何内容都会将其多次写入文件。 - Chris Shain
2
尝试在代码之前加入Thread.Sleep(10000);,并将当前时间(包括秒数!)嵌入文件名中。因此,如果执行两次,则应该看到两个不同的文件名。 - Akos Lukacs
1
虽然有些愚蠢,但你确定该按钮只被点击了一次吗?你是否有机制来禁用该按钮,直到下载完成? - Siva Gopal
显示剩余6条评论
3个回答

0
您可以查看以下代码行的用途:
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则用于从应用程序服务器下载到客户端机器。 - iJade

0

好的,所以真正的罪魁祸首是Response.WriteFile。在我的情况下,我想可能是由于数据量很大,Response.WriteFile没有按预期工作。我在某个地方发现,在下载大文件的情况下,最好使用Response.TransmitFile。没有其他选择,我改变了我的代码并使用了Response.TransmitFile,结果问题解决了。下载的文件中不再有重复的记录。尽管原因仍然未知,但Response.TransmitFile解决了这个问题.....


0
显然有一些可疑的事情正在发生。你说它在开发环境中可以工作但在生产环境中不能 - 你是否在两个环境中使用相同的服务器配置(即在开发中使用1台服务器,在生产中使用2台服务器?)
假设我已经理解了你的代码,那么你可能有3个步骤...
  • 从SQL生成报告并将其写入文件
  • 如果文件存储在不同的服务器上,请将其下载到Web服务器
  • 提供服务
所以,在更复杂的场景中(我假设生产环境是这样的),在哪个步骤中您开始看到重复条目?在生成报告的服务器上,在Web服务器的副本上还是只有在从Web服务器获取之后才出现在客户端上?
我看不出为什么你用于向客户端提供文件的代码会重复数据,因此只能假设在某个时候之前发生了重复。
如果你能使用Firebug/Fiddler/???来发布Web服务器到客户端传输的确切内容,那将非常有帮助。
(顺便说一句,你可能需要查看System.IO.Path类来操作路径,它使你的代码更易读和健壮 - 不再担心尾随斜线!)

数据重复的问题在第三步......我认为罪魁祸首是Response.WriteFile,因为我的文件相当大......我正在生产环境中测试Response.TransmitFile....会继续更新。 - iJade
@jade 你考虑过打开Step Into .Net Framework源代码并查看Response.WriteFile();的操作吗? - Basic
这应该是一个库,我怎么进入 Response.WriteFile 函数? - iJade
工具->选项->调试->常规。勾选“启用.NET Framework源码步进”。如果尚未设置符号,您需要进行设置。 - Basic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接