Skip to content

Commit

Permalink
- Changed pdf generation to push html to the generator (#539)
Browse files Browse the repository at this point in the history
- Avoid multiple convertions between string and stream when generating pdf
- Bumped storage.interface to 4.0.3

Co-authored-by: Henning Normann <[email protected]>
  • Loading branch information
HenningNormann and HenningNormann authored Nov 1, 2024
1 parent b68d207 commit 38a5dd9
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/Storage/Altinn.Platform.Storage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<PackageReference Include="Altinn.Common.AccessTokenClient" Version="3.0.8" />
<PackageReference Include="Altinn.Platform.Models" Version="1.6.1" />
<PackageReference Include="Altinn.Platform.Storage.Interface" Version="4.0.2" />
<PackageReference Include="Altinn.Platform.Storage.Interface" Version="4.0.3" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.2" />
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.7.0" />
Expand Down
2 changes: 1 addition & 1 deletion src/Storage/Clients/IPdfGeneratorClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ public interface IPdfGeneratorClient
/// Generates a PDF.
/// </summary>
/// <returns>A stream with the binary content of the generated PDF</returns>
Task<Stream> GeneratePdf(string url, bool isPortrait);
Task<Stream> GeneratePdf(string html, bool isPortrait);
}
}
21 changes: 15 additions & 6 deletions src/Storage/Clients/PdfGeneratorClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class PdfGeneratorClient: IPdfGeneratorClient
private readonly HttpClient _httpClient;
private readonly ILogger<PdfGeneratorClient> _logger;
private static readonly JsonSerializerOptions _jsonSerializerOptions =
new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull };

/// <summary>
/// Initializes a new instance of the <see cref="PdfGeneratorClient"/> class.
Expand All @@ -40,10 +40,13 @@ public PdfGeneratorClient(
}

/// <inheritdoc/>
public async Task<Stream> GeneratePdf(string url, bool isPortrait)
public async Task<Stream> GeneratePdf(string html, bool isPortrait)
{
var request = new PdfGeneratorRequest() { Url = url };
request.Options = new() { Landscape = !isPortrait };
var request = new PdfGeneratorRequest
{
Html = html,
Options = new() { Landscape = !isPortrait }
};
string requestContent = JsonSerializer.Serialize(request, _jsonSerializerOptions);
var httpResponseMessage = await _httpClient.PostAsync(_httpClient.BaseAddress, new StringContent(requestContent, Encoding.UTF8, "application/json"));

Expand Down Expand Up @@ -73,9 +76,15 @@ public async Task<Stream> GeneratePdf(string url, bool isPortrait)
public class PdfGeneratorRequest
{
/// <summary>
/// The Url that the PDF generator will used to obtain the HTML needed to created the PDF.
/// The Url that the PDF generator will used to obtain the HTML needed to created the PDF
/// if Html is not specified. Don't use both!
/// </summary>
public string Url { get; set; }

/// <summary>
/// The html that is input to the PDF generator if Url is not specified. Don't use both!
/// </summary>
public string Url { get; set; } = string.Empty;
public string Html { get; set; }

/// <summary>
/// PDF generator request options.
Expand Down
24 changes: 14 additions & 10 deletions src/Storage/Controllers/ContentOnDemandController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Xml.Linq;
using Altinn.Platform.Storage.Clients;
using Altinn.Platform.Storage.Configuration;
using Altinn.Platform.Storage.Interface.Models;
Expand Down Expand Up @@ -151,10 +153,8 @@ public async Task<Stream> GetFormdataAsPdf([FromRoute] string org, [FromRoute] s
using var mergedDoc = new PdfDocument();
foreach (var xsl in xsls)
{
var pdfPages = await _pdfGeneratorClient.GeneratePdf(
$"{Request.Scheme}://{Request.Host}{Request.PathBase}{Request.Path}"
.Replace("formdatapdf", $"formdatahtml/{xsl.PageNumber}"),
xsl.IsPortrait);
string html = await GetFormdataAsHtmlString(app, instanceGuid, dataGuid, language, 3, xsl.PageNumber);
var pdfPages = await _pdfGeneratorClient.GeneratePdf(html, xsl.IsPortrait);
using var pageDoc = PdfReader.Open(pdfPages, PdfDocumentOpenMode.Import);
for (var i = 0; i < pageDoc.PageCount; i++)
{
Expand All @@ -170,9 +170,8 @@ public async Task<Stream> GetFormdataAsPdf([FromRoute] string org, [FromRoute] s
else
{
// Generate all pages in a single operation
return await _pdfGeneratorClient.GeneratePdf(
$"{Request.Scheme}://{Request.Host}{Request.PathBase}{Request.Path}".Replace("formdatapdf", "formdatahtml"),
xsls[0].IsPortrait);
string html = await GetFormdataAsHtmlString(app, instanceGuid, dataGuid, language, 3);
return await _pdfGeneratorClient.GeneratePdf(html, xsls[0].IsPortrait);
}
}

Expand All @@ -189,7 +188,7 @@ public async Task<Stream> GetFormdataAsPdf([FromRoute] string org, [FromRoute] s
[HttpGet("formdatahtml/{singlepagenr?}")]
public async Task<Stream> GetFormdataAsHtml([FromRoute]string org, [FromRoute] string app, [FromRoute] Guid instanceGuid, [FromRoute] Guid dataGuid, [FromRoute] string language, [FromRoute(Name = "singlepagenr")] int singlePageNr = -1)
{
return await GetFormdataAsHtmlInternal(org, app, instanceGuid, dataGuid, language, 3, singlePageNr);
return await GetFormdataAsHtmlStream(app, instanceGuid, dataGuid, language, 3, singlePageNr);
}

/// <summary>
Expand All @@ -204,10 +203,15 @@ public async Task<Stream> GetFormdataAsHtml([FromRoute]string org, [FromRoute] s
[HttpGet("formsummaryhtml")]
public async Task<Stream> GetFormSummaryAsHtml([FromRoute] string org, [FromRoute] string app, [FromRoute] Guid instanceGuid, [FromRoute] Guid dataGuid, [FromRoute] string language)
{
return await GetFormdataAsHtmlInternal(org, app, instanceGuid, dataGuid, language, 2);
return await GetFormdataAsHtmlStream(app, instanceGuid, dataGuid, language, 2);
}

private async Task<Stream> GetFormdataAsHtmlInternal(string org, string app, Guid instanceGuid, Guid dataGuid, string language, int viewType, int singlePageNr = -1)
private async Task<Stream> GetFormdataAsHtmlStream(string app, Guid instanceGuid, Guid dataGuid, string language, int viewType, int singlePageNr = -1)
{
return new MemoryStream(Encoding.UTF8.GetBytes(await GetFormdataAsHtmlString(app, instanceGuid, dataGuid, language, viewType, singlePageNr)));
}

private async Task<string> GetFormdataAsHtmlString(string app, Guid instanceGuid, Guid dataGuid, string language, int viewType, int singlePageNr = -1)
{
(Instance instance, _) = await _instanceRepository.GetOne(instanceGuid, true);
Application application = await _applicationRepository.FindOne(instance.AppId, instance.Org);
Expand Down
4 changes: 2 additions & 2 deletions src/Storage/Repository/PgInstanceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ private async Task<InstanceQueryResponse> GetInstancesInternal(
previousId = id;
}

if (!reader.IsDBNull("element"))
if (!await reader.IsDBNullAsync("element"))
{
instance.Data.Add(await reader.GetFieldValueAsync<DataElement>("element"));
}
Expand Down Expand Up @@ -342,7 +342,7 @@ private async Task<InstanceQueryResponse> GetInstancesInternal(
instanceInternalId = await reader.GetFieldValueAsync<long>("id");
}

if (includeElements && !reader.IsDBNull("element"))
if (includeElements && !await reader.IsDBNullAsync("element"))
{
instanceData.Add(await reader.GetFieldValueAsync<DataElement>("element"));
}
Expand Down
4 changes: 2 additions & 2 deletions src/Storage/Services/A2OndemandFormattingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ public A2OndemandFormattingService(IA2Repository a2Repository, ILogger<A2Ondeman
}

/// <inheritdoc/>
public Stream GetFormdataHtml(PrintViewXslBEList printXslList, Stream xmlData, string archiveStamp)
public string GetFormdataHtml(PrintViewXslBEList printXslList, Stream xmlData, string archiveStamp)
{
return new MemoryStream(Encoding.UTF8.GetBytes(GetFormdataHtmlInternal(xmlData, printXslList, archiveStamp)));
return GetFormdataHtmlInternal(xmlData, printXslList, archiveStamp);
}

private string GetFormdataHtmlInternal(
Expand Down
4 changes: 2 additions & 2 deletions src/Storage/Services/IA2OndemandFormattingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public interface IA2OndemandFormattingService
/// <param name="printXslList">printXslList</param>
/// <param name="xmlData">xmlData</param>
/// <param name="archiveStamp">Timestamp used for water mark</param>
/// <returns>Html as stream</returns>
Stream GetFormdataHtml(PrintViewXslBEList printXslList, Stream xmlData, string archiveStamp);
/// <returns>Html as string</returns>
string GetFormdataHtml(PrintViewXslBEList printXslList, Stream xmlData, string archiveStamp);
}
}

0 comments on commit 38a5dd9

Please sign in to comment.