I use .net core2 ASP.NET Boilerplate.
Because my webapi is dynamic created from application. In application architecture there is no “return File()” method because of not inherit from .net core mvc controller.
So I want implement downloadFile by Writing data to HttpContext Response.
In .net4.x, I use this code writing data to response, and it work well. but when I use it in .netcore, it does not work.
public static void WriteWorkBookToResponse(this IWorkbook book, HttpContext httpContext, string fileName)
{
var response = httpContext.Response;
using (var exportData = new MemoryStream())
{
response.Clear();
book.Write(exportData);
response.ContentType = "application/vnd.ms-excel";
response.Headers.Add("Content-Disposition", $"attachment;filename={fileName}.xls");
response.Body.Write(exportData.GetBuffer());
}
}
In logs,this is a error "System.InvalidOperationException: StatusCode cannot be set because the response has already started".
"at Abp.AspNetCore.Security.AbpSecurityHeadersMiddleware.Invoke(HttpContext httpContext) in D:\Github\aspnetboilerplate\src\Abp.AspNetCore\AspNetCore\Security\AbpSecurityHeadersMiddleware.cs:line 26".
I read .net core mvc source code and edit my code. like below:
public static async void WriteToResponse2(this IWorkbook book, HttpContext httpContext, string templateName)
{
var response = httpContext.Response;
using (var exportData = new MemoryStream())
{
book.Write(exportData);
// response.ContentLength = exportData.GetBuffer().Length;
response.ContentType = "application/vnd.ms-excel";
SetContentDispositionHeader(httpContext, templateName);
await StreamCopyOperation.CopyToAsync(exportData, response.Body, count: null, bufferSize: 64 * 1024, cancel: httpContext.RequestAborted);
}
}
private static void SetContentDispositionHeader(HttpContext httpContext, string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
var contentDisposition = new Microsoft.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
contentDisposition.SetHttpFileName(fileName);
httpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
}
}
Then the api return "406 Error:Not Acceptable", the file downloaded can not open, is damaged.
I need help, I will be thankful for you helping me.