PDF Dönüşüm Servisi
PDF oluşturma, CPU ve bellek yoğun bir işlemdir. Ana uygulamanızın içinde PDF render etmek; hem performansı düşürür hem de ölçeklendirmeyi zorlaştırır. html-to-pdf bu sorunu bağımsız bir mikroservis olarak çözer — Playwright'ın headless Chromium motoru ile piksel mükemmelliğinde PDF çıktısı üretir.
GitHub'da Açık Kaynak
html-to-pdf — .NET 9, Playwright, Minimal API üzerine inşa edilmiş, MIT lisanslı açık kaynak proje. github.com/mersel-os/html-to-pdf
Kurulum, yapılandırma veya production ortamına taşıma konusunda desteğe mi ihtiyacınız var? Ekibimizle iletişime geçin — projenizi birlikte hayata geçirelim. Tüm açık kaynak projelerimiz için açık kaynak sayfamızı ziyaret edin.
Neden Ayrı Bir Mikroservis?
| Avantaj | Açıklama |
|---|---|
| Yük İzolasyonu | PDF oluşturma izole edilir, ana servisleriniz etkilenmez |
| Yatay Ölçeklendirme | Yoğun dönemlerde replica sayısını artırın |
| Bağımsız Kaynak Yönetimi | PDF servisine 1 GB, ana uygulamaya 512 MB gibi ayrı limitler |
| Modern Altyapı | Playwright ile tam CSS3, Flexbox, Grid ve JavaScript desteği |
| Stateless | Load balancer arkasında istediğiniz kadar kopya çalıştırın |
Tek instance ile başlayın, ihtiyaç büyüdükçe replica sayısını artırın. Servis tamamen stateless çalışır — her istek kendi tarayıcı context'inde izole şekilde yürütülür.
Özellikler
- Tekli HTML → PDF — Tam CSS/JS desteğiyle her türlü HTML belgesini PDF'e dönüştürür
- Çoklu HTML → Birleştirilmiş PDF — Birden fazla HTML'i tek PDF'te birleştirir
- Chromium Render — Playwright'ın headless Chromium motoru ile piksel mükemmelliğinde çıktı
- PDF Birleştirme — PdfSharpCore ile çoklu belge birleştirme
- Otomatik Tarayıcı Kurulumu — Chromium ilk çalıştırmada otomatik indirilir
- İstemci SDK'sı — .NET tüketicileri için hazır NuGet paketi
- Scalar API Dokümantasyonu —
/scalar/v1adresinde etkileşimli API referansı - Docker Hazır — Sağlık kontrolü dahil üretime hazır Dockerfile
- 73 Test — Birim, entegrasyon ve performans/stres testleri (gerçek e-fatura şablonlarıyla)
Hızlı Başlangıç
Servisi Çalıştırma
dotnet run --project src/Web
Servis http://localhost:5090 adresinde başlar. İlk çalıştırmada Playwright otomatik olarak Chromium'u indirir.
Docker ile Çalıştırma
docker build -t mersel-htmltopdf .
docker run -p 5090:8080 mersel-htmltopdf
API Endpoint'leri
| Metod | Adres | Açıklama |
|---|---|---|
GET | /health | Sağlık kontrolü (Chromium durumu dahil) |
POST | /convert | Tek HTML → PDF dönüşümü |
POST | /convert/merge | Çoklu HTML → Birleştirilmiş PDF |
GET | /metrics | Prometheus metrikleri |
GET | /scalar/v1 | Scalar API dokümantasyon arayüzü |
GET | /openapi/v1.json | OpenAPI spesifikasyonu |
Tek HTML → PDF
# Varsayılan ayarlarla
curl -X POST http://localhost:5090/convert \
-F "file=@fatura.html" \
-o cikti.pdf
# Landscape, özel kenar boşlukları
curl -X POST "http://localhost:5090/convert?landscape=true&marginTop=25mm&marginBottom=25mm" \
-F "file=@rapor.html" \
-o rapor.pdf
# Akıllı küçültme + JS bekleme (wkhtmltopdf uyumlu davranış)
curl -X POST "http://localhost:5090/convert?smartShrinking=true&jsDelay=2000" \
-F "file=@fatura.html" \
-o cikti.pdf
Çoklu HTML → Tek PDF
curl -X POST http://localhost:5090/convert/merge \
-F "files=@sayfa1.html" \
-F "files=@sayfa2.html" \
-F "files=@sayfa3.html" \
-o birlesmis.pdf
Sağlık Kontrolü
curl http://localhost:5090/health
{
"status": "Healthy",
"service": "HtmlToPdf",
"duration": 0.42,
"checks": [
{
"name": "chromium",
"status": "Healthy",
"description": "Chromium tarayıcısı bağlı ve hazır",
"duration": 0.12
}
]
}
Tüm PDF Ayarları
| Parametre | Tip | Varsayılan | Açıklama |
|---|---|---|---|
format | string | A4 | Kağıt boyutu (A3, A4, A5, Letter, Legal, Tabloid) |
landscape | bool | false | Yatay sayfa yönü |
scale | float | 1.0 | Render ölçek faktörü (0.1 – 2.0) |
printBackground | bool | true | Arka plan renk/resimlerini yazdır |
marginTop | string | 10mm | Üst kenar boşluğu |
marginBottom | string | 10mm | Alt kenar boşluğu |
marginLeft | string | 5mm | Sol kenar boşluğu |
marginRight | string | 5mm | Sağ kenar boşluğu |
displayHeaderFooter | bool | false | Header/Footer şablonu göster |
headerTemplate | string | — | Header HTML şablonu |
footerTemplate | string | — | Footer HTML şablonu |
jsDelay | int | — | JavaScript bekleme süresi (ms) |
waitForNetworkIdle | bool | false | Ağ istekleri tamamlanana kadar bekle |
smartShrinking | bool | false | İçerik taşarsa otomatik küçült |
preferCssPageSize | bool | false | CSS @page boyutunu tercih et |
pageRanges | string | — | Sayfa aralıkları (ör: "1-5", "1,3,5-9") |
.NET İstemci SDK
Kurulum
dotnet add package MERSEL.Services.HtmlToPdf.Client
| Paket | Açıklama | Hedef Framework |
|---|---|---|
MERSEL.Services.HtmlToPdf.Client | HTTP istemci SDK'sı + DI uzantıları | net8.0 |
MERSEL.Services.HtmlToPdf.Application | Sadece IHtmlToPdfConverter arayüzü | net8.0, net9.0 |
DI Kaydı
// Yapılandırma dosyasından
builder.Services.AddHtmlToPdfClient(builder.Configuration);
// Veya doğrudan URL belirterek
builder.Services.AddHtmlToPdfClient("http://htmltopdf-service:8080");
Kullanım
public class FaturaServisi(IHtmlToPdfConverter pdfConverter)
{
// Basit kullanım (varsayılan: A4, dikey, arka plan açık)
public async Task<byte[]> FaturaPdfOlustur(string htmlIcerik)
{
var htmlBytes = Encoding.UTF8.GetBytes(htmlIcerik);
return await pdfConverter.ConvertAsync(htmlBytes);
}
// wkhtmltopdf uyumlu preset ile
public async Task<byte[]> EFaturaPdfOlustur(string htmlIcerik)
{
var htmlBytes = Encoding.UTF8.GetBytes(htmlIcerik);
return await pdfConverter.ConvertAsync(
htmlBytes, PdfConvertOptions.WkHtmlCompatible);
}
// Özel ayarlarla
public async Task<byte[]> RaporPdfOlustur(string htmlIcerik)
{
var htmlBytes = Encoding.UTF8.GetBytes(htmlIcerik);
return await pdfConverter.ConvertAsync(htmlBytes, new PdfConvertOptions
{
Landscape = true,
MarginTop = "25mm",
MarginBottom = "25mm",
SmartShrinking = true,
JavaScriptDelayMs = 2000
});
}
// Birden fazla HTML'i tek PDF'te birleştirme
public async Task<byte[]> TopluFaturaPdf(List<string> htmlSayfalar)
{
var htmlByteList = htmlSayfalar.Select(Encoding.UTF8.GetBytes);
return await pdfConverter.ConvertAndMergeAsync(htmlByteList);
}
}
Hazır Preset'ler
| Preset | Açıklama |
|---|---|
PdfConvertOptions.WkHtmlCompatible | wkhtmltopdf uyumlu: akıllı küçültme, JS bekleme (2sn), dar kenar boşlukları |
PdfConvertOptions.WkHtmlMergeCompatible | Birleştirme için: daha uzun JS bekleme (5sn) |
new PdfConvertOptions() | Varsayılan: A4, dikey, ölçek 1.0, arka plan açık |
wkhtmltopdf'den Geçiş
wkhtmltopdf artık bakım almıyor ve modern web standartlarını desteklemiyor. Bu servise geçmek için:
Parametre Karşılıkları
| wkhtmltopdf | Bu servis | Açıklama |
|---|---|---|
--page-size A4 | format=A4 | Kağıt boyutu |
--orientation Landscape | landscape=true | Sayfa yönü |
--enable-smart-shrinking | smartShrinking=true | İçerik küçültme |
--javascript-delay 2000 | jsDelay=2000 | JS bekleme süresi |
--margin-top 5 | marginTop=5mm | Üst kenar boşluğu |
--margin-bottom 5 | marginBottom=5mm | Alt kenar boşluğu |
--print-media-type | printBackground=true | Arka plan yazdırma (varsayılan açık) |
--header-html ... | headerTemplate=... | Sayfa üst bilgisi |
--footer-html ... | footerTemplate=... | Sayfa alt bilgisi |
| Birden fazla HTML girdi | /convert/merge endpoint | Çoklu HTML → tek PDF |
Kod Değişikliği
// Önce (wkhtmltopdf)
var converter = new WkHtmlToPdfConverter();
var pdf = converter.Convert(htmlString, "--page-size A4 --enable-smart-shrinking ...");
// Sonra (MERSEL.Services.HtmlToPdf)
public class FaturaServisi(IHtmlToPdfConverter pdfConverter)
{
public async Task<byte[]> Olustur(string html)
{
var htmlBytes = Encoding.UTF8.GetBytes(html);
return await pdfConverter.ConvertAsync(
htmlBytes, PdfConvertOptions.WkHtmlCompatible);
}
}
PdfConvertOptions.WkHtmlCompatible preset'i, eski --enable-smart-shrinking davranışını birebir karşılar. Çoğu durumda tek satır değişiklik yeterlidir.
Yatay Ölçeklendirme
Servis tamamen stateless olduğu için load balancer arkasında sorunsuz ölçeklenir.
Docker Compose — 3 Replica
services:
htmltopdf:
build: .
deploy:
replicas: 3
resources:
limits:
memory: 1G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
nginx:
image: nginx:alpine
ports:
- "5090:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- htmltopdf
Kubernetes ortamında HorizontalPodAutoscaler ile CPU kullanımına göre otomatik ölçeklendirme yapabilirsiniz.
Observability
Prometheus Metrikleri (/metrics)
| Metrik | Tip | Açıklama |
|---|---|---|
htmltopdf_conversions_total | Counter | Toplam başarılı dönüşüm (etiket: type=single|merge) |
htmltopdf_conversions_errors_total | Counter | Başarısız dönüşüm sayısı |
htmltopdf_conversion_duration_milliseconds | Histogram | Dönüşüm süresi |
htmltopdf_pdf_size_bytes | Histogram | Oluşturulan PDF boyutu |
htmltopdf_conversions_active | Gauge | Devam eden aktif dönüşüm |
Grafana Dashboard
monitoring/ klasöründe hazır dashboard, tek komutla kurulur:
cd monitoring
docker compose up -d --build
| Servis | Adres |
|---|---|
| HtmlToPdf | http://localhost:5090 |
| Prometheus | http://localhost:9090 |
| Grafana | http://localhost:3000 (admin / htmltopdf) |
Dashboard 4 bölümden oluşur:
- Genel Bakış — Toplam dönüşüm, hata oranı, aktif dönüşüm, ortalama süre, PDF boyutu
- Dönüşüm Performansı — İstek hızı, süre dağılımı (p50/p95/p99), tekli vs birleştirme
- HTTP İstekleri — Durum koduna göre istek hızı, yanıt süresi, endpoint bazında trafik
- .NET Runtime — GC heap, thread pool, proses bellek, CPU kullanımı
Performans
| Özellik | Detay |
|---|---|
| Chromium Singleton | Tarayıcı uygulama ömrü boyunca tek instance olarak ayakta kalır |
| Context İzolasyonu | Her dönüşüm kendi tarayıcı context'inde çalışır |
| Eşzamanlılık | Tek instance birden fazla eşzamanlı isteği karşılar |
| Tipik Performans | Tek sayfalık fatura HTML'i ~50-100ms'de PDF'e dönüşür |
Sonuç
html-to-pdf, PDF dönüşümünü ana uygulamanızdan ayırarak hem performansı hem de ölçeklenebilirliği artırır. wkhtmltopdf'den geçiş minimum kod değişikliği gerektirir; hazır preset'ler ve .NET SDK ile dakikalar içinde entegre olursunuz.
Kurulum ve Entegrasyon Desteği
PDF dönüşüm servisini kurmak, wkhtmltopdf'den geçiş yapmak veya mevcut altyapınıza entegre etmek için uzman ekibimizden destek alın.
Bize Ulaşın- GitHub: github.com/mersel-os/html-to-pdf
- Detay Sayfası: Proje Detayları
- NuGet: MERSEL.Services.HtmlToPdf.Client
- Lisans: MIT