下载文件导致用户退出
Posted
技术标签:
【中文标题】下载文件导致用户退出【英文标题】:Downloading file causes user to be logged out 【发布时间】:2020-06-26 10:29:59 【问题描述】:我有一个 ASP.NET MVC 4.5.2 网站(由于托管限制),其中有一个带有操作链接的管理员限制区域,当用户点击该链接时,该链接会为用户下载 .csv 或 .xlsx 文件。
在本地它工作得很好。
但是,当发布到生产环境时,单击下载按钮会导致用户退出并显示登录屏幕,就好像他们没有经过身份验证一样。然后,登录会真正开始下载(因为 returnUrl 被设置为下载按钮的操作链接)。
以下代码 sn-ps 是我所拥有的修剪版本:
管理员控制器
[Authorize(Roles = "Admin")]
public class AdminController : BaseController
...
[HttpGet]
public ActionResult Users()
var users = _context.PreSignups
.Where(x => x.IsDeleted == false)
.OrderBy(x => x.DateCreated).ToList();
CheckMessages();
return View(users);
[HttpGet]
public ActionResult Download_PreSignupUsersToExcel()
var users = _context.PreSignups
.Where(x => x.IsDeleted == false)
.OrderBy(x => x.DateCreated).ToList().ToDataTable();
DocumentService.WriteToSpreadsheet(users, $"PreSignupUsers_DateTime.UtcNow.ToString("yyyy_MM_dd_hh_mm_ss").xlsx", true, Response);
// NOTE: Due to the Response being sent back in DocumentService.WriteToSpreadsheet() the below is mostly redundant as the response has already closed by this point.
TempData["Message"] = "Download started";
return RedirectToAction("Logs", "Admin");
DocumentService.cs
public static void WriteToSpreadsheet(DataTable dt, string filename, bool hasHeaders, HttpResponseBase response, enFileType fileType = enFileType.Xlsx)
... // Build the data
// Write the data
using (var exportData = new MemoryStream())
response.Clear();
workbook.Write(exportData);
if (fileType == enFileType.Xlsx) //xlsx file format
response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.AddHeader("Content-Disposition", $"attachment;filename=filename");
response.BinaryWrite(exportData.ToArray());
else if (fileType == enFileType.Xls) //xls file format
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", $"attachment;filename=filename");
response.BinaryWrite(exportData.GetBuffer());
response.End();
观点
在某些时候包含以下操作链接以对上述内容进行 GET 调用。单击此按钮会导致用户明显以"admin/Download_PreSignupUsersToExcel"
作为returnUrl 注销到登录屏幕。
@html.ActionLink("Export .Xlsx", "Download_PreSignupUsersToExcel", "Admin", null, new @class="btn btn-primary" )
作为参考,BaseController 继承自 Controller 类,并提供了一种存储 ApplicationDbContext 和 LoggingService 的便捷方式,并且对上述内容没有任何影响。
我已经对代码视而不见了。
有什么想法吗?
【问题讨论】:
【参考方案1】:好的,事实证明浏览器只会监听特定请求的单个响应。
我将代码的下载部分移到了它自己的 AdminDownloadController API 中。然后通过删除response.End();
并返回带有所有相关数据的HttpResponseMessage
并用它替换控制器中的标准ActionResult
,下载在同一个经过身份验证和授权的会话中启动,而无需注销用户。
需要注意的是,如果没有一些 JS 魔法,您无法对客户端的响应做很多事情,例如显示消息。 AJAX 调用在身份验证和授权方面存在问题,因此请选择阻力最小的路径...除非您遇到这种情况!
以下是适用于任何需要它的人的代码摘要:
AdminDownloadController.cs
[Authorize(Roles = "Admin")]
public class AdminDownloadController : BaseApiController
// GET: api/AdminDownload/PreSignupUsersToExcel
public HttpResponseMessage Get(string downloadName)
var response = new HttpResponseMessage(HttpStatusCode.NotFound);
switch (downloadName)
case "PreSignupUsersToExcel":
var users1 = _context.PreSignups
.Where(x => x.IsDeleted == false)
.OrderByDescending(x => x.DateCreated).ToList().ToDataTable();
response = DocumentService.WriteToSpreadsheet(users1, $"PreSignupUsers_DateTime.UtcNow.ToString("yyyy_MM_dd_hh_mm_ss").xlsx", true);
break;
...
return response;
DocumentService.cs
public static HttpResponseMessage WriteToSpreadsheet(DataTable dt, string filename, bool hasHeaders, enFileType fileType = enFileType.Xlsx)
// Build Data
...
// StreamData
using (var exportData = new MemoryStream())
workbook.Write(exportData);
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new ByteArrayContent(exportData.ToArray());
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = filename;
if (fileType == enFileType.Xlsx)
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
else if (fileType == enFileType.Xls)
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel");
return response;
WhateverView.cshtml
...
@Html.ActionLink("Export .Xlsx", "AdminDownload", "Api", new downloadName = "PreSignupUsersToExcel" , new @class = "btn btn-primary" )
...
【讨论】:
以上是关于下载文件导致用户退出的主要内容,如果未能解决你的问题,请参考以下文章
我记得迅雷有一个DLL文件 把它放在根目录能大大提升下载速度(像是)