From 0f6ec4dc2ab2a113b704a358392a447762cb95e3 Mon Sep 17 00:00:00 2001 From: Mauro Ghiani Date: Wed, 9 Oct 2024 06:54:50 +0000 Subject: [PATCH] Download reports Related work items: #491 --- .../FattureAccontoFatturaExcelPersistence.cs | 2 +- .../Infrastructure/ConfigurationExtensions.cs | 5 ++++ .../Extensions/NotificaExtensions.cs | 25 +++++++++++------ .../Modules/Notifiche/NotificaModule.cs | 28 +++++++++++++++---- .../PortaleFatture.BE.Api/appsettings.json | 11 +++++++- 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelPersistence.cs b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelPersistence.cs index 2277e24..20abe81 100644 --- a/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelPersistence.cs +++ b/src/Infrastructure/PortaleFatture.BE.Infrastructure/Common/Fatture/Queries/Persistence/FattureAccontoFatturaExcelPersistence.cs @@ -14,7 +14,7 @@ public class FattureAccontoFatturaExcelPersistence(FattureAccontoExcelQuery comm { var anno = _command.Anno; var mese = _command.Mese; - var where = " where n.year= @anno and n.month=@mese "; + var where = " where f.Anno= @anno and f.mese=@mese "; if (!_command.IdEnti!.IsNullNotAny()) where = " AND t.FKIdEnte in @IdEnti "; diff --git a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs index 779a2ae..3f5f49b 100644 --- a/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs +++ b/src/Presentation/PortaleFatture.BE.Api/Infrastructure/ConfigurationExtensions.cs @@ -40,6 +40,11 @@ public static IServiceCollection AddModules(this WebApplicationBuilder builder) var configuration = builder.Configuration; var isProd = builder.Environment.IsProduction(); + builder.WebHost.ConfigureKestrel(options => + { + options.Configure(configuration.GetSection("Kestrel")); + }); + PortaleFattureOptions options = new(); configuration.GetSection(nameof(PortaleFattureOptions)).Bind(options); diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs index b187eb9..56ab1b8 100644 --- a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/Extensions/NotificaExtensions.cs @@ -31,23 +31,30 @@ public static NotificaQueryGetByListaEntiv2 Mapv2(this NotificheRicercaRequestPa public static async Task Download(this HttpContext context, byte[]? data, string mime, string filename) { - - context.Response.ContentType = mime; + var totalBytes = data!.Length; + context.Response.ContentType = mime; context.Response.Headers.TryAdd("Content-Disposition", $"attachment; filename={filename}"); - - const int bufferSize = 16 * 1024; + context.Response.Headers["Content-Length"] = totalBytes.ToString(); + + const int bufferSize = 32 * 1024; var buffer = new byte[bufferSize]; - var totalBytes = data!.Length; var bytesRemaining = totalBytes; - var offset = 0; - + var offset = 0; + + int flushCounter = 0; while (bytesRemaining > 0) { var chunkSize = Math.Min(bufferSize, bytesRemaining); Buffer.BlockCopy(data, offset, buffer, 0, chunkSize); - await context.Response.Body.WriteAsync(buffer, 0, chunkSize); - await context.Response.Body.FlushAsync(); + await context.Response.Body.WriteAsync(buffer, 0, chunkSize); + + flushCounter++; + if (flushCounter % 10 == 0) + { + await context.Response.Body.FlushAsync(); + } + offset += chunkSize; bytesRemaining -= chunkSize; } diff --git a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs index 036c2a0..58d7b46 100644 --- a/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs +++ b/src/Presentation/PortaleFatture.BE.Api/Modules/Notifiche/NotificaModule.cs @@ -1,4 +1,6 @@ -using System.Globalization; +using System.Collections; +using System.Globalization; +using System.IO; using CsvHelper; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -140,7 +142,7 @@ private async Task, NotFound>> UpdatePagoPAContestazio [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] - private async Task GetPagoPANotificheRicercaDocumentAsync( + private async Task GetPagoPANotificheRicercaDocumentAsync( HttpContext context, [FromBody] NotificheRicercaRequestPagoPA request, [FromServices] IStringLocalizer localizer, @@ -151,15 +153,29 @@ private async Task GetPagoPANotificheRicercaDocumentAsync( var notifiche = await handler.Send(request.Map(authInfo, null, null)); if (notifiche == null || notifiche.Count == 0) { - await Results.NotFound("Data not found").ExecuteAsync(context); - return; + //await Results.NotFound("Data not found").ExecuteAsync(context); + //return; + return NotFound(); } var data = await notifiche.Notifiche!.ToArray(); + if (data == null || data.Length == 0) + { + //await Results.NotFound("Data not found").ExecuteAsync(context); + //return; + return NotFound(); + } + var filename = $"{Guid.NewGuid()}.csv"; - var mimeCsv = "text/csv"; - await context.Download(data, mimeCsv, filename); + var mimeCsv = "text/csv"; + //await context.Download(data, mimeCsv, filename); + var stream = new MemoryStream(data!); + stream.Position = 0; + // Now you can use the stream + // For example, returning it in an ASP.NET Core action + return Results.Stream(stream, mimeCsv, filename); + //return Results.File(data!, mimeCsv, filename); } #endregion diff --git a/src/Presentation/PortaleFatture.BE.Api/appsettings.json b/src/Presentation/PortaleFatture.BE.Api/appsettings.json index dac05c9..945b57d 100644 --- a/src/Presentation/PortaleFatture.BE.Api/appsettings.json +++ b/src/Presentation/PortaleFatture.BE.Api/appsettings.json @@ -32,5 +32,14 @@ "Synapse:PipelineNameSAP": "PIPELINE_NAME_SAP", "Synapse:SubscriptionId": "SYNAPSE_SUBSCRIPTIONID", "Synapse:ResourceGroupName": "SYNAPSE_RESOURCEGROUPNAME" - } + }, + "Kestrel": { + "Limits": { + "MaxRequestBodySize": 2147483648, + "RequestTimeout": "00:10:00", + "MaxResponseBufferSize": 1048576, + "KeepAliveTimeout": "00:10:00", + "RequestHeadersTimeout": "00:10:00" + } + } } \ No newline at end of file