Stil ve karakter kaybı olmadan HTML/XML'i PDF'e dönüştürme
Karmaşık düzeni koruyarak ve Kiril alfabesini doğru görüntüleyerek HTML veya XML'i yüksek kalitede PDF'e dönüştürmek için HTML için Chromium tabanlı render motorları (örneğin Puppeteer) veya XML için XSL-FO işlemcileri (örneğin Apache FOP) kullanmanız gerekir. Başarının anahtar koşulları: UTF-8 kodlamasının zorunlu kullanımı, yazı tiplerinin nihai dosyaya gömülmesi (embedding) ve CSS'in @media print medya sorgusu aracılığıyla baskı ortamlarına uyarlanmasıdır.
Aşağıda öngörülebilir sonuç garantisi veren kanıtlanmış yöntemler, araçlar ve ayarlar ele alınmıştır.
Kısa cevap: HTML için en uygun seçenek headless tarayıcıdır (Chrome/Puppeteer), çünkü modern CSS standartlarını destekler. Sıkı yapılandırılmış XML için XSLT + XSL-FO + Apache FOP kombinasyonunu kullanın. Yazı tiplerini her zaman PDF'e gömün.
Dönüşüm sırasındaki temel sorunlar
Bir araç seçmeden önce, sürecin en sık nerede bozulduğunu anlamak önemlidir:
- Karakter kodlaması. Kaynak dosya UTF-8 değilse veya yazı tipi gerekli glifleri (örneğin Kiril alfabesini) desteklemiyorsa, PDF'de "anlamsız karakterler" veya boş kareler görünür.
- Stil kaybı. Birçok hafif dönüştürücü Flexbox, Grid veya karmaşık CSS3 seçicilerini yok sayar.
- Sayfa sonları.
break-insidekuralları belirtilmezse metin satırın veya tablonun ortasında kesilebilir. - Eksik kaynaklar. Göreceli yollarla bağlanan görseller ve yazı tipleri, sunucu tarafında oluşturma sırasında yüklenmeyebilir.
Yöntem 1: HTML'i PDF'e Dönüştürme (Headless Chrome / Puppeteer)
Bu, web geliştiricileri için en popüler yöntemdir. Kullanıcının tarayıcısıyla aynı motoru kullandığı için görsel doğruluk maksimum düzeydedir.
Neden işe yarar
Headless Chrome, sayfayı tamamen render eder, JavaScript'i çalıştırır ve CSS'i uygular, ardından onu PDF olarak "yazdırır".
Ortamın yapılandırılması
HTML belgenizin standartlara uygun olduğundan emin olun:
- Kodlama açıkça belirtilmiş olmalı:
<meta charset="UTF-8">. - Yazı tipleri doğru şekilde bağlanmış olmalı (yerel dosyaları veya güvenilir CDN'leri kullanmak daha iyidir).
Örnek yapılandırma (Node.js + Puppeteer)
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Sayfaya gidin veya HTML'i bir dizeden yükleyin
await page.goto('https://example.com/invoice.html', { waitUntil: 'networkidle0' });
await page.pdf({
path: 'document.pdf',
format: 'A4',
printBackground: true, // Önemli: Arka plan renklerini ve görselleri yazdır
margin: {
top: '20mm',
right: '20mm',
bottom: '20mm',
left: '20mm'
},
preferCSSPageSize: true // CSS @page içindeki boyutları kullan
});
await browser.close();
})();
CSS İpucu: Gereksiz öğeleri (menüler, site altbilgileri) gizlemek ve sayfa sonlarını ayarlamak için @media print medya sorgusunu kullanın.
@media print {
.no-print { display: none; }
tr { break-inside: avoid; } /* Tablo satırlarının bölünmesini engelle */
}
Yöntem 2: XML'i PDF'e Dönüştürme (XSL-FO + Apache FOP)
Elinizde saf XML verileri varsa (örneğin, 1C'den alınan dışa aktarmalar, banka raporları), doğrudan HTML'e dönüştürme gereksiz olabilir. Buradaki endüstri standardı XSL-FO'dur (Formatting Objects).
Eylem algoritması
- XML: Kaynak veriler.
- XSLT: XML'i ara biçim XSL-FO'ya dönüştürme (sayfa düzeni, sütunlar, yazı tipleri açıklaması).
- FOP (Apache FOP): FO dosyasını PDF'e dönüştüren işlemci.
Avantajlar
- Öğelerin konumlandırılması üzerinde tam kontrol (mutlak doğruluk).
- Sıkı yapıya sahip belgeler için mükemmel (faturalar, tutanaklar, irsaliyeler).
- Tarayıcı motorlarından bağımsızlık.
FOP'ta yazı tipi ayarları
Kiril alfabesinin doğru görüntülenmesi için yazı tiplerinin fop.xconf yapılandırma dosyasında kaydedilmesi gerekir:
<fonts>
<font embed-url="fonts/arial.ttf">
<font-triplet name="Arial" style="normal" weight="normal"/>
</font>
<font embed-url="fonts/arialbd.ttf">
<font-triplet name="Arial" style="normal" weight="bold"/>
</font>
</fonts>
Araçların karşılaştırılması
| Araç | Kaynak türü | CSS Kalitesi | Yapılandırma zorluğu | Lisans |
|---|---|---|---|---|
| Puppeteer / Playwright | HTML | Mükemmel (CSS3) | Düşük | Open Source |
| wkhtmltopdf | HTML | Orta (eskidi) | Düşük | Open Source |
| PrinceXML | HTML/XML | Mükemmel (Paged Media) | Orta | Ticari |
| Apache FOP | XML (FO) | Özel (FO) | Yüksek | Open Source |
| WeasyPrint | HTML | İyi (CSS Paged) | Orta | Open Source |
Dikkat: wkhtmltopdf artık aktif olarak desteklenmemekte ve eski WebKit motorunu kullanmaktadır. Modern projeler için Puppeteer veya WeasyPrint kullanılması önerilir.
Kodlamalar ve yazı tipleri ile çalışma
Nihai dosyada karakterlerin eksik olması en sık yapılan hatadır. Sorunlardan kaçınmak için bir kontrol listesi:
- Her zaman UTF-8 kullanın. Bu, hem HTML meta etiketinde, hem HTTP başlıklarında, hem de XML işlemci ayarlarında belirtilmelidir.
- Yazı tiplerini gömme (Embedding). Kullanıcının veya sunucunun bilgisayarında gerekli yazı tipinin yüklü olduğunu varsaymayın.
- CSS'de:
.ttfveya.woff2dosya yolunu belirten@font-face. - Dönüştürücü ayarlarında:
embedFontsbayrağını (veya eşdeğerini) etkinleştirin.
- CSS'de:
- Glif desteğinin kontrol edilmesi. Seçilen yazı tipinin Kiril karakterlerini içerdiğinden emin olun. Times New Roman veya Arial gibi standart yazı tipleri genellikle uygundur, ancak özel web yazı tiplerini kontrol etmeniz gerekir.
Sık yapılan hatalar ve çözümleri
1. Kesilmiş tablolar
Sorun: Tablo satırı sayfalar arasında bölünür, metnin bir kısmı kaybolur. Çözüm: CSS'e şunu ekleyin:
table, tr, td, th {
break-inside: avoid;
}
2. Metin yerine boş kareler
Sorun: Yazı tipi gömülmemiş veya dili desteklemiyor. Çözüm: Yazı tipi yükleme hataları için dönüştürücü günlüklerini kontrol edin. Yazı tipi yolunun mutlak olduğundan veya çalışma dizinine göre doğru belirtildiğinden emin olun.
3. Yanlış girintiler ve kenar boşlukları
Sorun: Yazıcı, sizin kenar boşluklarınızın üzerine kendi kenar boşluklarını ekler.
Çözüm: PDF ayarlarında body için CSS'de açıkça margin: 0 belirtin ve kenar boşluklarını yalnızca aracın parametreleri üzerinden (örneğin Puppeteer'da margin) veya @page { margin: 2cm; } aracılığıyla yönetin.
SSS
Soru: JavaScript grafikleri içeren karmaşık HTML dönüştürülebilir mi?
Evet, Headless Chrome (Puppeteer/Playwright) kullanılırsa. PDF oluşturmadan önce grafiklerin tamamen render edilmesini beklemek için waitUntil: 'networkidle0' veya belirli bir seçicinin beklenmesi kullanılır.
Soru: Toplu fatura oluşturma için hangi araç seçilmeli? Faturalar XML verilerinden oluşturuluyorsa — Apache FOP veya ticari PrinceXML (hem HTML hem de XML kabul edebilir). Düzen HTML/CSS üzerinde yapılıyorsa — Puppeteer. PrinceXML, tipografik kalite için genellikle daha tercih edilir, ancak ücretlidir.
Soru: Nihai PDF'in boyutu nasıl küçültülür? Kullanılmayan yazı tipi karakterlerinin gömülmesini devre dışı bırakın (subsetting). Çoğu modern araç bunu varsayılan olarak yapar, ancak ayarları kontrol etmek iyi olur. Ayrıca, HTML/XML'e eklemeden önce görselleri optimize edin.
Soru: Dönüştürme hiper bağlantıları destekliyor mu?
Evet, standart <a href="..."> etiketleri, herhangi bir modern dönüştürücü kullanıldığında PDF'de etkin bağlantılar olarak korunur.