Skip to content

Commit

Permalink
(#70) Export Html, Pdf Files
Browse files Browse the repository at this point in the history
  • Loading branch information
phongnguyend committed Jul 3, 2021
1 parent 20fc109 commit 1e3cea2
Show file tree
Hide file tree
Showing 53 changed files with 863 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Migrations/
/src/UIs/reactjs/.eslintcache
.tye/
.local-chromium/

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Threading.Tasks;

namespace ClassifiedAds.CrossCuttingConcerns.HtmlGenerator
{
public interface IHtmlGenerator
{
Task<string> GenerateAsync(string template, object model);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.IO;
using System.Threading.Tasks;

namespace ClassifiedAds.CrossCuttingConcerns.PdfConverter
{
public interface IPdfConverter
{
Stream Convert(string html, PdfOptions pdfOptions = null);

Task<Stream> ConvertAsync(string html, PdfOptions pdfOptions = null);
}

public class PdfOptions
{

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<PackageReference Include="Confluent.Kafka" Version="1.5.2" />
<PackageReference Include="CryptographyHelper" Version="1.0.0-beta4" />
<PackageReference Include="Dapper.StrongName" Version="2.0.35" />
<PackageReference Include="DinkToPdf" Version="1.0.8" />
<PackageReference Include="Google.Protobuf" Version="3.10.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.25.0" />
<PackageReference Include="IdentityModel" Version="4.4.0" />
Expand Down Expand Up @@ -60,7 +61,9 @@
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.0.0-rc1.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc1.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc1.1" />
<PackageReference Include="PuppeteerSharp" Version="4.0.0" />
<PackageReference Include="RabbitMQ.Client" Version="6.2.1" />
<PackageReference Include="RazorLight" Version="2.0.0-rc.3" />
<PackageReference Include="SendGrid" Version="9.21.2" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
Expand All @@ -79,4 +82,15 @@
<ProjectReference Include="..\ClassifiedAds.Domain\ClassifiedAds.Domain.csproj" />
</ItemGroup>

<ItemGroup>
<ContentWithTargetPath Include="..\libs\libwkhtmltox\libwkhtmltox-0.12.4-x64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libwkhtmltox.dll</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="..\libs\libwkhtmltox\libwkhtmltox-0.12.4-x64.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libwkhtmltox.so</TargetPath>
</ContentWithTargetPath>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using ClassifiedAds.CrossCuttingConcerns.HtmlGenerator;
using RazorLight;
using System.Threading.Tasks;

namespace ClassifiedAds.Infrastructure.HtmlGenerators
{
public class HtmlGenerator : IHtmlGenerator
{
private readonly IRazorLightEngine _razorLightEngine;

public HtmlGenerator(IRazorLightEngine razorLightEngine)
{
_razorLightEngine = razorLightEngine;
}

public Task<string> GenerateAsync(string template, object model)
{
return _razorLightEngine.CompileRenderAsync(template, model);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using ClassifiedAds.CrossCuttingConcerns.HtmlGenerator;
using ClassifiedAds.Infrastructure.HtmlGenerators;
using RazorLight;
using System;

namespace Microsoft.Extensions.DependencyInjection
{
public static class HtmlGeneratorCollectionExtensions
{
public static IServiceCollection AddHtmlGenerator(this IServiceCollection services)
{
var engine = new RazorLightEngineBuilder()
.UseFileSystemProject(Environment.CurrentDirectory)
.UseMemoryCachingProvider()
.Build();

services.AddSingleton<IRazorLightEngine>(engine);
services.AddSingleton<IHtmlGenerator, HtmlGenerator>();

return services;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using ClassifiedAds.CrossCuttingConcerns.PdfConverter;
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;
using System.Threading.Tasks;

namespace ClassifiedAds.Infrastructure.PdfConverters.DinkToPdf
{
public class DinkToPdfConverter : IPdfConverter
{
private readonly IConverter _converter;

public DinkToPdfConverter(IConverter converter)
{
_converter = converter;
}

public Stream Convert(string html, PdfOptions pdfOptions = null)
{
var doc = new HtmlToPdfDocument()
{
GlobalSettings =
{
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
Margins = new MarginSettings() { Top = 10, Bottom = 15, Left = 10, Right = 10 },
},
Objects =
{
new ObjectSettings()
{
PagesCount = true,
HtmlContent = html,
WebSettings = { DefaultEncoding = "utf-8", Background = true },
HeaderSettings = { FontSize = 9, Right = "Page [page] of [toPage]", Line = true, Spacing = 2.812 },
},
},
};

byte[] pdf = _converter.Convert(doc);

return new MemoryStream(pdf);
}

public Task<Stream> ConvertAsync(string html, PdfOptions pdfOptions = null)
{
return Task.FromResult(Convert(html, pdfOptions));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using ClassifiedAds.CrossCuttingConcerns.PdfConverter;
using ClassifiedAds.Infrastructure.PdfConverters.DinkToPdf;
using DinkToPdf;
using DinkToPdf.Contracts;

namespace Microsoft.Extensions.DependencyInjection
{
public static class DinkToPdfConverterCollectionExtensions
{
public static IServiceCollection AddDinkToPdfConverter(this IServiceCollection services)
{
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
services.AddSingleton<IPdfConverter, DinkToPdfConverter>();

return services;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using ClassifiedAds.CrossCuttingConcerns.PdfConverter;
using PuppeteerSharp;
using System.IO;
using System.Threading.Tasks;

namespace ClassifiedAds.Infrastructure.PdfConverters.PuppeteerSharp
{
public class PuppeteerSharpConverter : IPdfConverter
{
public Stream Convert(string html, CrossCuttingConcerns.PdfConverter.PdfOptions pdfOptions = null)
{
return ConvertAsync(html, pdfOptions).GetAwaiter().GetResult();
}

public async Task<Stream> ConvertAsync(string html, CrossCuttingConcerns.PdfConverter.PdfOptions pdfOptions = null)
{
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html);
return new MemoryStream(await page.PdfDataAsync(new global::PuppeteerSharp.PdfOptions
{
PrintBackground = true,
}));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using ClassifiedAds.CrossCuttingConcerns.PdfConverter;
using ClassifiedAds.Infrastructure.PdfConverters.PuppeteerSharp;
using PuppeteerSharp;

namespace Microsoft.Extensions.DependencyInjection
{
public static class PuppeteerSharpConverterCollectionExtensions
{
public static IServiceCollection AddPuppeteerSharpPdfConverter(this IServiceCollection services)
{
var browserFetcher = new BrowserFetcher();
browserFetcher.DownloadAsync().GetAwaiter().GetResult();

services.AddSingleton<IPdfConverter, PuppeteerSharpConverter>();

return services;
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,15 @@
<ProjectReference Include="..\..\Common\ClassifiedAds.Infrastructure\ClassifiedAds.Infrastructure.csproj" />
</ItemGroup>

<PropertyGroup>
<PreserveCompilationReferences>true</PreserveCompilationReferences>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>

<ItemGroup>
<Content Update="Templates\ProductList.cshtml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using ClassifiedAds.Application;
using ClassifiedAds.CrossCuttingConcerns.HtmlGenerator;
using ClassifiedAds.CrossCuttingConcerns.PdfConverter;
using ClassifiedAds.Infrastructure.Web.Authorization.Policies;
using ClassifiedAds.Services.Product.Authorization.Policies.Products;
using ClassifiedAds.Services.Product.Commands;
Expand All @@ -12,7 +14,9 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Threading.Tasks;

namespace ClassifiedAds.Services.Product.Controllers
Expand All @@ -25,11 +29,17 @@ public class ProductsController : ControllerBase
{
private readonly Dispatcher _dispatcher;
private readonly ILogger _logger;
private readonly IHtmlGenerator _htmlGenerator;
private readonly IPdfConverter _pdfConverter;

public ProductsController(Dispatcher dispatcher, ILogger<ProductsController> logger)
public ProductsController(Dispatcher dispatcher, ILogger<ProductsController> logger,
IHtmlGenerator htmlGenerator,
IPdfConverter pdfConverter)
{
_dispatcher = dispatcher;
_logger = logger;
_htmlGenerator = htmlGenerator;
_pdfConverter = pdfConverter;
}

[AuthorizePolicy(typeof(GetProductsPolicy))]
Expand Down Expand Up @@ -132,5 +142,18 @@ public async Task<ActionResult<IEnumerable<AuditLogEntryDTO>>> GetAuditLogs(Guid

return Ok(entries.OrderByDescending(x => x.CreatedDateTime));
}

[HttpGet("exportaspdf")]
public async Task<IActionResult> ExportAsPdf()
{
var products = await _dispatcher.DispatchAsync(new GetProductsQuery());
var model = products.ToModels();

var template = Path.Combine(Environment.CurrentDirectory, $"Templates/ProductList.cshtml");
var html = await _htmlGenerator.GenerateAsync(template, model);
var pdf = await _pdfConverter.ConvertAsync(html);

return File(pdf, MediaTypeNames.Application.Octet, "Products.pdf");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public void ConfigureServices(IServiceCollection services)
services.AddDateTimeProvider();
services.AddApplicationServices();

services.AddHtmlGenerator();
services.AddDinkToPdfConverter();

services.AddProductModule(AppSettings);

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
Expand Down
Loading

0 comments on commit 1e3cea2

Please sign in to comment.