Skip to content

Commit 262ec1c

Browse files
committed
Add WkHtmlToPdf
1 parent dd57482 commit 262ec1c

File tree

13 files changed

+233
-2
lines changed

13 files changed

+233
-2
lines changed

App/App.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<ProjectReference Include="..\Libs\QuestPdfLib\QuestPdfLib.csproj" />
1616
<ProjectReference Include="..\Libs\SelectPdfLib\SelectPdfLib.csproj" />
1717
<ProjectReference Include="..\Libs\SpirePdfLib\SpirePdfLib.csproj" />
18+
<ProjectReference Include="..\Libs\WkHtmlToPdfLib\WkHtmlToPdfLib.csproj" />
1819
</ItemGroup>
1920

2021
<ItemGroup>

App/Program.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using QuestPdfLib;
1212
using SelectPdfLib;
1313
using SpirePdfLib;
14+
using WkHtmlToPdfLib;
1415

1516
var services = new ServiceCollection();
1617
services
@@ -24,7 +25,8 @@
2425
.AddPuppeteerPdfLib()
2526
.AddQuestPdfLib()
2627
.AddSelectPdfLib()
27-
.AddSpirePdfLib();
28+
.AddSpirePdfLib()
29+
.AddWkHtmlToPdfLib();
2830

2931
var serviceProvider = services.BuildServiceProvider();
3032
foreach (var pdfGenerator in serviceProvider.GetServices<IPdfGenerator>())

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<PackageVersion Include="DinkToPdf.Standard" Version="1.1.0" />
1111
<PackageVersion Include="AwesomeAssertions" Version="9.1.0" />
1212
<PackageVersion Include="FreeSpire.PDF" Version="8.6.0" />
13+
<PackageVersion Include="Haukcode.WkHtmlToPdfDotNet" Version="1.5.95" />
1314
<PackageVersion Include="HtmlToPdfConverter.Core" Version="2.0.0" />
1415
<PackageVersion Include="IronPdf" Version="2024.12.9" />
1516
<PackageVersion Include="itext7" Version="9.3.0" />

Libs/DinkToPdfLib/DependencyInjection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public static class DependencyInjection
99
{
1010
public static IServiceCollection AddDinkToPdfLib(this IServiceCollection services)
1111
{
12-
services.AddTransient<IConverter>(_ => new StaSynchronizedConverter(new PdfTools()));
12+
services.AddSingleton<IConverter>(_ => new StaSynchronizedConverter(new PdfTools()));
1313
services.AddTransient<IPdfGenerator, HtmlPdfGenerator>();
1414
return services;
1515
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Contracts;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using WkHtmlToPdfDotNet;
4+
using WkHtmlToPdfDotNet.Contracts;
5+
6+
namespace WkHtmlToPdfLib;
7+
8+
public static class DependencyInjection
9+
{
10+
public static IServiceCollection AddWkHtmlToPdfLib(this IServiceCollection services)
11+
{
12+
services.AddSingleton<IConverter>(_ => new StaSynchronizedConverter(new PdfTools()));
13+
services.AddTransient<IPdfGenerator, HtmlPdfGenerator>();
14+
return services;
15+
}
16+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using Contracts;
2+
using WkHtmlToPdfDotNet;
3+
using WkHtmlToPdfDotNet.Contracts;
4+
5+
namespace WkHtmlToPdfLib;
6+
7+
public sealed class HtmlPdfGenerator : IPdfGenerator
8+
{
9+
private const int FontSizeToUse = 12;
10+
private const string FontNameToUse = "Ariel";
11+
private const string EncodingToUse = "utf-8";
12+
private const ColorMode ColorModeToUse = ColorMode.Color;
13+
private const PaperKind PaperSizeToUse = PaperKind.A4Plus;
14+
private const Orientation OrientationToUse = Orientation.Landscape;
15+
16+
private readonly IConverter _converter;
17+
18+
public HtmlPdfGenerator(IConverter converter)
19+
{
20+
_converter = converter;
21+
}
22+
23+
[STAThread]
24+
public Task GenerateAsync(string text, string filename, CancellationToken cancellationToken)
25+
{
26+
var html = $"<h1 style=\"font-size:100px;color:blue;\">{text}</h1>";
27+
var document = new HtmlToPdfDocument
28+
{
29+
GlobalSettings =
30+
{
31+
Out = filename,
32+
PaperSize = PaperSizeToUse,
33+
ColorMode = ColorModeToUse,
34+
Orientation = OrientationToUse
35+
},
36+
Objects =
37+
{
38+
new ObjectSettings
39+
{
40+
PagesCount = true,
41+
HtmlContent = html,
42+
WebSettings = { DefaultEncoding = EncodingToUse },
43+
HeaderSettings = { FontSize = FontSizeToUse, FontName = FontNameToUse }
44+
}
45+
}
46+
};
47+
_converter.Convert(document);
48+
return Task.CompletedTask;
49+
}
50+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System.Collections.Concurrent;
2+
using System.Runtime.InteropServices;
3+
using WkHtmlToPdfDotNet;
4+
using WkHtmlToPdfDotNet.Contracts;
5+
6+
namespace WkHtmlToPdfLib;
7+
8+
/// <summary>
9+
/// See issue : https://github.com/rdvojmoc/DinkToPdf/issues/119
10+
/// </summary>
11+
public sealed class StaSynchronizedConverter : BasicConverter
12+
{
13+
private bool _kill;
14+
private Thread? _conversionThread;
15+
private readonly Lock _startLock = new();
16+
private readonly BlockingCollection<Task> _conversions = [];
17+
18+
public StaSynchronizedConverter(ITools tools) : base(tools)
19+
{
20+
}
21+
22+
public override byte[] Convert(IDocument document)
23+
{
24+
return Invoke(() => base.Convert(document));
25+
}
26+
27+
private TResult Invoke<TResult>(Func<TResult> @delegate)
28+
{
29+
StartThread();
30+
31+
var task = new Task<TResult>(@delegate);
32+
33+
lock (task)
34+
{
35+
_conversions.Add(task);
36+
Monitor.Wait(task);
37+
}
38+
39+
if (task.Exception != null)
40+
{
41+
throw task.Exception;
42+
}
43+
44+
return task.Result;
45+
}
46+
47+
private void StartThread()
48+
{
49+
lock (_startLock)
50+
{
51+
if (_conversionThread == null)
52+
{
53+
_conversionThread = new Thread(Run)
54+
{
55+
IsBackground = true,
56+
Name = "wkhtmltopdf worker thread"
57+
};
58+
59+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
60+
{
61+
_conversionThread.SetApartmentState(ApartmentState.STA);
62+
}
63+
64+
_kill = false;
65+
66+
_conversionThread.Start();
67+
}
68+
}
69+
}
70+
71+
private void Run()
72+
{
73+
while (!_kill)
74+
{
75+
var task = _conversions.Take();
76+
77+
lock (task)
78+
{
79+
task.RunSynchronously();
80+
Monitor.Pulse(task);
81+
}
82+
}
83+
}
84+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<ItemGroup>
4+
<PackageReference Include="Haukcode.WkHtmlToPdfDotNet" />
5+
</ItemGroup>
6+
7+
<ItemGroup>
8+
<ProjectReference Include="..\..\Contracts\Contracts.csproj" />
9+
</ItemGroup>
10+
11+
</Project>

PdfGeneratorDemo.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DinkToPdfLib", "Libs\DinkTo
6161
EndProject
6262
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DinkToPdfLibTests", "Tests\DinkToPdfLibTests\DinkToPdfLibTests.csproj", "{B8746D6A-1C3E-42CF-8590-E1D2C6BD73B6}"
6363
EndProject
64+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WkHtmlToPdfLib", "Libs\WkHtmlToPdfLib\WkHtmlToPdfLib.csproj", "{59092653-23FE-4429-B26E-7DA96CEC428D}"
65+
EndProject
66+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WkHtmlToPdfLibTests", "Tests\WkHtmlToPdfLibTests\WkHtmlToPdfLibTests.csproj", "{7FF6B45B-E376-4CA2-AA1F-7A41EF6C0AE7}"
67+
EndProject
6468
Global
6569
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6670
Debug|Any CPU = Debug|Any CPU
@@ -155,6 +159,14 @@ Global
155159
{B8746D6A-1C3E-42CF-8590-E1D2C6BD73B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
156160
{B8746D6A-1C3E-42CF-8590-E1D2C6BD73B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
157161
{B8746D6A-1C3E-42CF-8590-E1D2C6BD73B6}.Release|Any CPU.Build.0 = Release|Any CPU
162+
{59092653-23FE-4429-B26E-7DA96CEC428D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
163+
{59092653-23FE-4429-B26E-7DA96CEC428D}.Debug|Any CPU.Build.0 = Debug|Any CPU
164+
{59092653-23FE-4429-B26E-7DA96CEC428D}.Release|Any CPU.ActiveCfg = Release|Any CPU
165+
{59092653-23FE-4429-B26E-7DA96CEC428D}.Release|Any CPU.Build.0 = Release|Any CPU
166+
{7FF6B45B-E376-4CA2-AA1F-7A41EF6C0AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
167+
{7FF6B45B-E376-4CA2-AA1F-7A41EF6C0AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
168+
{7FF6B45B-E376-4CA2-AA1F-7A41EF6C0AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
169+
{7FF6B45B-E376-4CA2-AA1F-7A41EF6C0AE7}.Release|Any CPU.Build.0 = Release|Any CPU
158170
EndGlobalSection
159171
GlobalSection(SolutionProperties) = preSolution
160172
HideSolutionNode = FALSE
@@ -180,6 +192,8 @@ Global
180192
{984592FE-C0D9-446C-A541-3B1D47754279} = {A852D5D4-4528-424B-978C-B04CA6D9A4F2}
181193
{53E688C5-A0F9-4970-9868-B49E642B671D} = {87F3D6C7-3C6B-41AD-94C0-A26C4D076CCF}
182194
{B8746D6A-1C3E-42CF-8590-E1D2C6BD73B6} = {A852D5D4-4528-424B-978C-B04CA6D9A4F2}
195+
{59092653-23FE-4429-B26E-7DA96CEC428D} = {87F3D6C7-3C6B-41AD-94C0-A26C4D076CCF}
196+
{7FF6B45B-E376-4CA2-AA1F-7A41EF6C0AE7} = {A852D5D4-4528-424B-978C-B04CA6D9A4F2}
183197
EndGlobalSection
184198
GlobalSection(ExtensibilityGlobals) = postSolution
185199
SolutionGuid = {B89CF2D0-E7E3-45A6-A487-1E4E2875AF75}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ In this demo, i m generating a pdf file using various libraries :
1616
- [DinkToPdf](https://github.com/hakanl/DinkToPdf)
1717
- [PuppeteerPdf](https://github.com/hardkoded/puppeteer-sharp)
1818
- [ITextSharpPdf](https://github.com/itext/itext7-dotnet)
19+
- [WkHtmlToPdf](https://github.com/HakanL/WkHtmlToPdf-DotNet)
1920

2021
**`Tools`** : net 9.0, pdf-generation

0 commit comments

Comments
 (0)