Проблема с заголовком ответа в веб-приложении Azure
Я не уверен, что здесь происходит.
Когда я запускаю свое веб-приложение локально и нажимаю кнопку, чтобы загрузить файл, файл загружается нормально и заголовок ответа, как вы можете видеть на прилагаемом скриншоте, где написано "локально".
Но когда я публикую приложение в лазурное веб-приложение. Почему-то перестает работать кнопка загрузки. Я проверил заголовок ответа, и вы можете увидеть разницу.
Что может вызвать эту проблему? Код такой же? Есть ли какие-либо настройки, которые я должен установить в веб-приложении Azure на портале Azure?
Обновлено, чтобы добавить код
Я отлаживал удаленно, чтобы выяснить, что происходит, как предложил @Amor.
Это так странно, что когда я отлаживаю на своей локальной машине, срабатывает первое действие ExportTo, которое подготавливает TempData, затем вызывается действие Download, как только первое действие завершается вызовом ajax.
Однако это не тот случай, когда я отлаживаю удаленно. Каким-то образом действие ExportTo никогда не вызывается. Он напрямую вызывает действие Download. В результате проверка нуля TempData всегда равна нулю.
Но почему? С какой стати и как это возможно? Где-то что-то кешируется?
Я удалил содержимое веб-приложения на удаленном компьютере и заново опубликовал все, чтобы все обновлялось. Но все равно безуспешно.
вот код:
[HttpPost]
public virtual ActionResult ExportTo(SearchVm searchVm)
{
var data = _companyService.GetCompanieBySearchTerm(searchVm).Take(150).ToList();
string handle = Guid.NewGuid().ToString();
TempData[handle] = data;
var fileName = $"C-{handle}.xlsx";
var locationUrl = Url.Action("Download", new { fileGuid = handle, fileName });
var downloadUrl = Url.Action("Download");
return Json(new { success = true, locationUrl, guid = handle, downloadUrl }, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult Download(string fileGuid, string fileName)
{
if (TempData[fileGuid] != null)
{
var fileNameSafe = $"C-{fileGuid}.xlsx";
var data = TempData[fileGuid] as List<Company>;
using (MemoryStream ms = new MemoryStream())
{
GridViewExtension.WriteXlsx(GetGridSettings(fileNameSafe), data, ms);
MVCxSpreadsheet mySpreadsheet = new MVCxSpreadsheet();
ms.Position = 0;
mySpreadsheet.Open("myDoc", DocumentFormat.Xlsx, () =>
{
return ms;
});
mySpreadsheet.Document.Worksheets.Insert(0);
var image = Server.MapPath("~/images/logo.png");
var worksheet = mySpreadsheet.Document.Worksheets[0];
worksheet.Name = "Logo";
worksheet.Pictures.AddPicture(image, worksheet.Cells[0, 0]);
byte[] result = mySpreadsheet.SaveCopy(DocumentFormat.Xlsx);
DocumentManager.CloseDocument("myDoc");
Response.Clear();
//Response.AppendHeader("Set-Cookie", "fileDownload=true; path=/");
Response.ContentType = "application/force-download";
Response.AddHeader("content-disposition", $"attachment; filename={fileNameSafe}");
Response.BinaryWrite(result);
Response.End();
}
}
return new EmptyResult();
}
вот JavaScript:
var exportData = function (urlExport) {
console.log('Export to link in searchController: ' + urlExport);
ExportButton.SetEnabled(false);
var objData = new Object();
var filterData = companyFilterData(objData);
console.log(filterData);
$.post(urlExport, filterData)
.done(function (data) {
console.log(data.locationUrl);
window.location.href = data.locationUrl;
});
};
При нажатии кнопки "Экспорт" вызывается функция exportData:
var exportToLink = '@Url.Action("ExportTo")';
console.log('Export to link in index: '+exportToLink);
SearchController.exportData(exportToLink);
Как я уже говорил, этот код отлично работает на локальной машине. В лазурном веб-приложении происходит нечто странное, что точка останова действия ExportTo никогда не попадает в цель.
Я не уверен, что еще я мог бы изменить, чтобы получить действие ExportTo?
1 ответ
Основываясь на заголовке ответа веб-приложения Azure, мы обнаруживаем, что значение Content-Length равно 0. Это означает, что данные не были отправлены со стороны сервера веб-приложения.
В ASP.NET MVC мы можем ответить на файл, используя следующие способы.
Первый способ, отправить файл, который размещен на сервере. Для этого проверьте, загружен ли файл Excel в Azure Web App. Вы можете использовать Kudu или FTP для папки, чтобы проверить, существует ли файл.
string fileLocation = Server.MapPath("~/Content/myfile.xlsx");
string contentType = System.Net.Mime.MediaTypeNames.Application.Octet;
string fileName = "file.xlsx";
return File(fileLocation, contentType, fileName);
Второй способ - мы можем прочитать файл из любого места (база данных, сервер или хранилище Azure) и отправить содержимое файла на клиентскую сторону. Для этого, пожалуйста, проверьте, был ли файл успешно прочитан. Вы можете выполнить удаленную отладку веб-приложения Azure, чтобы проверить, правильно ли прочитано содержимое файла.
byte[] fileContent = GetFileContent();
string contentType = System.Net.Mime.MediaTypeNames.Application.Octet;
string fileName = "file.xlsx";
return File(fileContent, contentType, fileName);
27.05.2017 Обновление
Каким-то образом действие ExportTo никогда не вызывается. Он напрямую вызывает действие Download. В результате проверка нуля TempData всегда равна нулю.
Сколько экземпляров назначено вашему веб-приложению? Если в вашем веб-приложении есть несколько экземпляров, запрос ExportTo обрабатывается одним экземпляром, а запрос на загрузку обрабатывается другим экземпляром. Поскольку TempData хранится в памяти выделенного экземпляра, его нельзя получить из другого экземпляра. По данным удаленного отладочного документа. Я выясняю причину, по которой действие ExportTo никогда не вызывается.
Если у вас есть несколько экземпляров веб-сервера, когда вы подключаетесь к отладчику, вы получаете случайный экземпляр, и у вас нет никакого способа гарантировать, что последующие запросы браузера будут идти к этому экземпляру.
Чтобы решить эту проблему, я предлагаю вам ответить на данные непосредственно из действия ExportTo или сохранить временные данные в хранилище BLOB-объектов Azure, к которым нельзя получить доступ из нескольких экземпляров.