Response.WriteFile пишет содержимое дважды
Вот мой код..
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 из местоположения. Но удивительно, что содержимое записывается дважды или несколько раз в файл, который я загружаю, хотя на самом деле это не так с файлом на сервере. Я пишу мой код в с #. Приведенный выше фрагмент кода отлично работает на локальном компьютере, но проблема заключается в производственном сервере.
Вот мой полный метод
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 ответа
Хорошо, так что настоящим виновником в этом случае был Response.WriteFile. В моем случае, я думаю, поскольку размер данных был довольно велик, Response.WriteFile не работал должным образом. Я нашел кое-где, что в случае загрузки больших файлов, лучше всего использовать Response.TransmitFile.Left без каких-либо других вариантов, я изменил свой код и использовал Response.TransmitFile и eureka! проблема была решена. В загруженном файле больше нет повторяющихся записей. Хотя причина до сих пор неизвестна, Response.TransmitFile решил проблему.....
Вы можете проверить, для чего предназначены следующие строки:
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();
}
Там явно что-то странное происходит. Вы сказали, что он работает в dev, но не в Prod. Используете ли вы одну и ту же конфигурацию сервера в обеих средах (т.е. используете ли вы 1 сервер в dev, а 2 в prod?)
У вас потенциально есть 3 шага, если я понял ваш код...
- Создать отчет из SQL и записать его в файл
- Если файл хранится на другом сервере, загрузите его на веб-сервер
- Служить
Итак, в более сложном сценарии (который я предполагаю, что производство), На каком этапе процесса вы начинаете видеть двойные записи? На сервере отчет генерируется, на копии веб-серверов или только на клиенте после получения его с веб-сервера?
Я не вижу никакой причины, по которой ваш код для передачи файла клиенту будет дублировать данные, поэтому я могу только предполагать, что это происходит раньше, в какой-то момент.
Было бы полезно, если бы вы могли использовать Firebug/Fiddler/??? опубликовать точное содержание передачи с веб-сервера клиенту
(Кстати, вы можете посмотреть на System.IO.Path
класс для манипулирования путями, он делает ваш код более читабельным и надежным - больше не нужно беспокоиться о конечных слешах!)