Response.TransmitFile Не скачивается, а выкидывает без ошибок
В настоящее время я использую HttpResponse для загрузки файлов с моего Сервера. У меня уже есть несколько функций, используемых для загрузки файлов Excel/Word, но у меня возникают проблемы с загрузкой моего простого текстового файла (.txt).
С помощью текстового файла я в основном выгружаю содержимое TextBox в файл, пытаясь загрузить файл с помощью HttpResponse, а затем удалить временный текстовый файл.
Вот пример моего кода, который работает для документов Excel/Word:
protected void linkInstructions_Click(object sender, EventArgs e)
{
String FileName = "BulkAdd_Instructions.doc";
String FilePath = Server.MapPath("~/TempFiles/BulkAdd_Instructions.doc");
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "application/x-unknown";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath);
response.Flush();
response.End();
}
И вот кусок кода, который не работает.
Принимая во внимание, что код выполняется без каких-либо ошибок. Файл создан и удален, но никогда не выгружается пользователю.
protected void saveLog(object sender, EventArgs e)
{
string date = DateTime.Now.ToString("MM_dd_yyyy_hhmm"); // Get Date/Time
string fileName = "BulkLog_"+ date + ".txt"; // Stitch File Name + Date/Time
string logText = errorLog.Text; // Get Text from TextBox
string halfPath = "~/TempFiles/" + fileName; // Add File Name to Path
string mappedPath = Server.MapPath(halfPath); // Create Full Path
File.WriteAllText(mappedPath, logText); // Write All Text to File
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
response.TransmitFile(mappedPath); // Transmit File
response.Flush();
System.IO.File.Delete(mappedPath); // Delete Temporary Log
response.End();
}
7 ответов
Я решил проблему самостоятельно. Оказывается, это была проблема Ajax, которая не позволяла моей кнопке должным образом выполнять обратную передачу. Это остановило TransmitFile от запуска.
Спасибо за помощь!
Это потому, что вы удаляете файл, прежде чем он может отправить.
Из MSDN - HttpResponse.End Метод
Отправляет весь текущий буферизованный вывод клиенту, останавливает выполнение страницы и вызывает событие EndRequest.
Попробуйте поместить ваш System.IO.File.Delete(mappedPath); строка после ответа.End(); в моем тесте именно тогда это, казалось, работало.
Кроме того, может быть хорошей идеей проверить, существует ли файл первым, не может увидеть какой-либо файл. Существует там, не хотят никаких исключений нулевой ссылки, и установить Content-Length.
РЕДАКТИРОВАТЬ: вот код, который я использовал в проекте на работе некоторое время назад, может помочь вам немного.
// Get the physical Path of the file
string filepath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + folder + filename;
// Create New instance of FileInfo class to get the properties of the file being downloaded
FileInfo file = new FileInfo(filepath);
// Checking if file exists
if (file.Exists)
{
// Clear the content of the response
Response.ClearContent();
// LINE1: Add the file name and attachment, which will force the open/cance/save dialog to show, to the header
Response.AddHeader("Content-Disposition", String.Format("attachment; filename={0}", file.Name));
// Add the file size into the response header
Response.AddHeader("Content-Length", file.Length.ToString());
// Set the ContentType
Response.ContentType = ReturnFiletype(file.Extension.ToLower());
// Write the file into the response (TransmitFile is for ASP.NET 2.0. In ASP.NET 1.1 you have to use WriteFile instead)
Response.TransmitFile(file.FullName);
// End the response
Response.End();
//send statistics to the class
}
А вот метод Filetype, который я использовал
//return the filetype to tell the browser.
//defaults to "application/octet-stream" if it cant find a match, as this works for all file types.
public static string ReturnFiletype(string fileExtension)
{
switch (fileExtension)
{
case ".htm":
case ".html":
case ".log":
return "text/HTML";
case ".txt":
return "text/plain";
case ".doc":
return "application/ms-word";
case ".tiff":
case ".tif":
return "image/tiff";
case ".asf":
return "video/x-ms-asf";
case ".avi":
return "video/avi";
case ".zip":
return "application/zip";
case ".xls":
case ".csv":
return "application/vnd.ms-excel";
case ".gif":
return "image/gif";
case ".jpg":
case "jpeg":
return "image/jpeg";
case ".bmp":
return "image/bmp";
case ".wav":
return "audio/wav";
case ".mp3":
return "audio/mpeg3";
case ".mpg":
case "mpeg":
return "video/mpeg";
case ".rtf":
return "application/rtf";
case ".asp":
return "text/asp";
case ".pdf":
return "application/pdf";
case ".fdf":
return "application/vnd.fdf";
case ".ppt":
return "application/mspowerpoint";
case ".dwg":
return "image/vnd.dwg";
case ".msg":
return "application/msoutlook";
case ".xml":
case ".sdxl":
return "application/xml";
case ".xdp":
return "application/vnd.adobe.xdp+xml";
default:
return "application/octet-stream";
}
}
Я наткнулся на этот пост в своем поиске и заметил, что бесполезно рассказывать нам, почему UpdatePanel вызвал проблему в первую очередь.
UpdatePanel является асинхронной обратной передачей, а Response.TransmitFile для полноценной работы требуется полная обратная передача.
Элемент управления, запускающий асинхронную обратную передачу, должен быть выполнен в UpdatePanel:
<Triggers>
<asp:PostBackTrigger ControlID="ID_of_your_control_that_causes_postback" />
</Triggers>
Спасибо за продолжение вашей проблемы. Я часами пытался понять, почему не выдается код ошибки, несмотря на то, что ничего не произошло. Оказывается, это была моя AJAX UpdatePanel таинственно и тайно мешала.
Я решил эту проблему. Для объекта Response требуется полная обратная передача, чтобы он мог загрузить файл Excel, созданный на сервере ... но полная обратная передача предотвращалась UpdatePanel в моей веб-форме, которая содержала мою кнопку экспорта. Итак ... внутри тега UpdatePanel я изменил это ...
<asp:AsyncPostBackTrigger ControlID="btnExport" EventName="Click" />
... к этому, чтобы решить проблему:
<asp:PostBackTrigger ControlID="btnExport"/>
Позвольте мне объяснить, что он имеет в виду. Вызовы Ajax очень полезны с точки зрения UX. Однако некоторые методы несовместимы с ним, как этот. Когда вы используете Ajax для загрузки файла с сервера, он будет работать отлично, пока не попытается отправить его клиенту Flush(), потому что Flush() не отправит обратно клиенту. Лучший способ решить эту проблему — заменить вызов Ajax на метод form post. На самом деле, это будет очень гладко и без HTML, если вы используете JavaScript для создания метода публикации формы. Кроме того, страница не перезагружается, поскольку выполняется только очистка. Вот пример JavaScript для замены вызова Ajax.
var form = document.createElement("form");
$(form).attr("action", "/Manage/DownloadFile");
$(form).attr("method", "post");
var input = document.createElement("input");
input.type = "hidden";
input.name = "FolderPath";
input.value = folderPath;
$(form).append(input);
$(document.body).append(form);
$(form).submit();