4

Here is my code..

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

I'm using the above code to download a csv file from a location.But surprisingly the contents gets written twice or some times thrice into the file that i download though actually it isn't so with the file on server.I'm writing my code in c#. The above piece of code works perfectly in local machine,but the issue is in Production server.

Here is my complete Method

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

And the above method is called only once straight away on click of a button,so no question of any looping here.

iJade
  • 23,144
  • 56
  • 154
  • 243
  • 3
    Check if method with this body is called more than once. I think it is... – Tomas Voracek Jun 26 '12 at 18:19
  • 5
    I think you have shown the wrong code snippet. It's the code that writes the file in `downloadLocation` that is probably faulty. – Darin Dimitrov Jun 26 '12 at 18:19
  • @DarinDimitrov Umm no it writes the contents of the specified file directly to an HTTP response output stream as a file block. – carny666 Jun 26 '12 at 18:23
  • Please attach output of HTTP traffic from Fiddler or similar. – Tomas Voracek Jun 26 '12 at 18:25
  • @TomasVoracek no it isn't since this thing works fine in local system.Issue only on production server – iJade Jun 26 '12 at 18:27
  • 1
    I'd bet @DarinDimitrov is right, and the problem is that whatever generates the report is writing it to the file multiple times. – Chris Shain Jun 26 '12 at 18:30
  • 2
    Try putting a `Thread.Sleep(10000);` right before your code, and embed the current time (including seconds!) in the file name. So if it's executed twice, you should see two different file names – Akos Lukacs Jun 26 '12 at 19:39
  • @ChrisShain i have updated my entire method – iJade Jun 27 '12 at 05:39
  • 1
    Though silly but are you sure that button is clicked only once? Do you have a mechanism in place to disable the button until the download is finished? – Siva Gopal Jun 27 '12 at 05:46
  • @SivaGopal well actually its only clicked once, i can surely say this coz on clicking download what i'm doing is writing the file from mysql server using 'Select into OUTFILE' and then fetching that file into our application server and den downloading this file using Response.WriteFile.i checked both the file on the mysql server and the application server both have the correct content(no repetition of data).Only repetition is found in the file downloaded using Response.WriteFile – iJade Jun 27 '12 at 05:51
  • @SivaGopal If the button were clicked twice, it may server the file twice but it would be 2 different connections and the data should never be appended – Basic Jun 27 '12 at 11:31

3 Answers3

0

You may check what the following lines are meant for :

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

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

Give a try by commenting out one of them, if they are really doing the same. As a safe measure, please disable the button until your download is finished.

When i tried the following code (even published on IIS), it is just downloading once, as expected.

 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();
        }
Siva Gopal
  • 3,474
  • 1
  • 25
  • 22
  • well webclient is for downloading data from Database server to application server and Response.WriteFile for downloading from application server to client machine – iJade Jun 27 '12 at 10:58
0

There's obviously something hinky going on. You've said that it works in dev but not Prod - Are you using the same server config in both environemts (ie are you using 1 server in dev but 2 in prod?)

You've potentially got 3 steps, assuming I've understood your code...

  • Generate Report from SQL and write it to a file
  • If the file is stored on a different server, download it to the web server
  • Serve it

So, in the more complex scenario (which I assume Production is), At what step in the process do you start to see double entries? On the server the report is generated on, on the web servers' copy or only in the client after getting it from the Webserver?

I can't see any reason why your code to serve the file to the client would be duplicating data so can only assume it's happening before there at some point.

It would be helpful if you could use Firebug/Fiddler/??? to post the exact contents of the transmission from the webserver to the client

(Incidentally, you may want to look at the System.IO.Path class for manipulating paths, it makes your code more readable and robust - No more worrying about trailing slashes!)

Basic
  • 26,321
  • 24
  • 115
  • 201
  • well data duplication is in 3rd step.....and i think the culprit is Response.WriteFile since my file is quite large.......i am testing with Response.TransmitFile on prod....will keep posted – iJade Jun 27 '12 at 11:56
  • @jade Have you considered turning on Step Into .Net Framework source and having a look at what it's doing in the `Response.WriteFile();`? – Basic Jun 27 '12 at 13:25
  • Its a library i guess, how can i step into Response.WriteFile?? – iJade Jun 27 '12 at 13:44
  • Tools->Options->Debugging->General. Tick `Enable .NET Framework source stepping`. You'll need to set up symbols if you haven't done so. – Basic Jun 27 '12 at 13:50
0

ok so the real culprit was Response.WriteFile in this case.In my case i guess since the size of data was quite huge Response.WriteFile was not working as expected.I found some where that in case of large file downloads, its best to use Response.TransmitFile.Left with no other option i changed my code and used Response.TransmitFile and eureka! the problem was solved.No more duplicate records in downloaded file.Though the reason is still unknown, Response.TransmitFile solved the issue.....

iJade
  • 23,144
  • 56
  • 154
  • 243