Загрузите Excel (NPOI), записав данные в ответ от динамического webapi - PullRequest
0 голосов
/ 10 сентября 2018

Я использую .net core2 ASP.NET Boilerplate.
Потому что мой webapi динамически создается из приложения. В архитектуре приложения отсутствует метод return File (), поскольку он не наследуется от контроллера .net core mvc.
Поэтому я хочу реализовать downloadFile, записав данные в HttpContext Response. В .net4.x я использую этот код для записи данных в ответ, и он работает хорошо. но когда я использую его в .netcore, он не работает.

    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());
        }
    }

В журналах это ошибка «System.InvalidOperationException: StatusCode не может быть установлен, потому что ответ уже запущен».
"at Abp.AspNetCore.Security.AbpSecurityHeadersMiddleware.Invoke (HttpContext httpContext) в D: \ Github \ aspnetboilerplate \ src \ Abp.AspNetCore \ AspNetCore \ Security \ AbpSecurityHeaders: 100.ware.base.id.

Я читаю исходный код MVC ядра .net и редактирую свой код. как показано ниже:

    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();
        }
    }

Затем API возвращает «406 Error: Not Acceptable», загруженный файл не открывается, поврежден.

Мне нужна помощь, я буду благодарен за вашу помощь.

1 Ответ

0 голосов
/ 10 сентября 2018

измените метод WriteToResponse2 на:

public static void WriteToResponse2(this IWorkbook book, HttpContext httpContext, string templateName)
{
    var response = httpContext.Response;
    response.ContentType = "application/vnd.ms-excel";
    SetContentDispositionHeader(httpContext, templateName);
    book.Write(response.Body);
}

При использовании в методе действия будьте осторожны, чтобы не изменять ответ снова.

public void Test2() {
    var newFile = @"newbook.core.docx";
    using (var fs = new FileStream(newFile, FileMode.Create, FileAccess.Write))
    {
        IWorkbook workbook = CreateBook();
        workbook.WriteToResponse2(contextAccessor.HttpContext,"ss.xlsx");
    }
}

Вот скриншот, он работает:

enter image description here

...