Azure Web 应用程序上的响应 Header 问题

Response Header issue on Azure Web Application

我不确定这里发生了什么。

当我在本地 运行 我的 Web 应用程序并单击按钮下载文件时,文件下载正常并且响应 header 正如您在随附的屏幕截图中看到的那样本地。

但是当我将应用程序发布到 azure web 应用程序时。下载按钮不知何故停止工作。我检查了响应 Header,您可以看到不同之处。

什么会导致这个问题?代码是一样的?我应该在 Azure 门户中的 Azure Web 应用程序中设置任何设置吗?

Updated to add code

我已经按照@Amor 的建议进行了远程调试以了解发生了什么。

这太奇怪了,当我在本地机器上调试时,第一个 ExportTo 操作被命中,它准备 TempData 然后下载操作在第一个操作完成 ajax 调用后被调用。

但是,我远程调试的时候却不是这样。不知何故,永远不会调用 ExportTo 操作。它直接调用下载操作。结果,TempData 空检查始终为空。

但是为什么呢?为什么在地球上,这怎么可能?有什么东西缓存在某处吗?

我已经擦除远程和 re-publish 上的 Web 应用程序的内容以确保所有内容都已更新。但是还是没有成功。

代码如下:

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

正如我提到的,这段代码在本地机器上运行完美。 Azure webapp 上发生了一些奇怪的事情,ExportTo 操作断点永远不会被击中。

我不确定我还可以更改哪些内容来命中 ExportTo 操作?

根据Azure Web App的Response Header,我们发现Content-Length的值为0,表示没有数据从Web App服务器端发送过来。

在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存储)读取文件并将文件内容发送到客户端。对于这种方式,请检查文件是否已成功读取。您可以remote debug your azure web app检查文件内容是否没有被正确读取。

byte[] fileContent = GetFileContent();
string contentType = System.Net.Mime.MediaTypeNames.Application.Octet;
string fileName = "file.xlsx";
return File(fileContent, contentType, fileName);

2017 年 5 月 27 日更新

Somehow the ExportTo action never gets called. It directly calls the Download action. As a result the TempData null checking is always null.

您的 Web App 分配了多少个实例?如果您的 Web 应用程序有多个实例,则 ExportTo 请求由一个实例处理,下载请求由另一个实例处理。由于 TempData 存储在专用实例的内存中,因此无法从其他实例获取。根据远程调试文档。我找出了 ExportTo 操作从未​​被调用的原因。

如果您有多个 Web 服务器实例,当您附加到调试器时,您将获得一个随机实例,并且您无法确保后续浏览器请求将转到该实例。

为了解决这个问题,我建议您直接从 ExportTo 操作响应数据或将临时数据保存在无法从多实例访问的 Azure blob 存储中。