Sıkıştırma ve alt küme oluşturma ile PDF dosya boyutunu küçültün
Bir bakışta
“Bir bakışta” başlıklı bölümİçeriğin izin verdiği ölçüde, doğruluktan ödün vermeden en küçük PDF’yi üretmek istiyorsunuz. NextPDF, dosya boyutu için size iki denetim sunar ve ikisi de varsayılan olarak açıktır:
- Akış sıkıştırması. Yazıcı, her sayfanın içerik akışını ve her gömülü yazı tipi programını bir FlateDecode (zlib) akışına sarar.
NextPDF\Core\Configiçindekicompressbayrağı bu ayarı tutar. Belgeyi akış olarak oluştururken bu ayarıwithCompress()wither yöntemiyle belirleyin. - Yazı tipi alt küme oluşturma. Bir TrueType veya CFF yazı tipi gömdüğünüzde, yazıcı yazı tipi programını yalnızca belgenin kullandığı glifleri içerecek şekilde yeniden oluşturur, ardından sonucu FlateDecode ile sıkıştırır. Bu işlem otomatik olarak gerçekleşir. Ayarlayacağınız bir bayrak veya yapacağınız bir çağrı yoktur. Bir belgede yalnızca birkaç yüz glifi kullanılan
20,000glifli bir CJK yazı tipi, disk boyutunun çok küçük bir bölümüyle gömülür.
Baştan açıkça belirtelim: NextPDF Core, görüntü yeniden örnekleme, görüntü kalitesi denetimi, nesne akışı düğmesi veya kaynak yinelenenlerini kaldırma ayarı sunmaz. Yukarıdaki iki denetim, tek boyut denetimleridir. Bu tarifin devamı, bunları doğru şekilde nasıl kullanacağınızı ve her birinin neyi yapmadığını gösterir.
Ön koşullar: bir Core kurulumu (composer require nextpdf/core:^3) ve alt küme oluşturma yolunda kullanmak üzere gömme lisansına sahip olduğunuz bir yazı tipi dosyası.
Kurulum
“Kurulum” başlıklı bölümcomposer require nextpdf/core:^3Kavramsal genel bakış
“Kavramsal genel bakış” başlıklı bölümBir PDF, nesnelerden oluşan bir ağaçtır. En büyük nesneler genellikle içerik akışları (her sayfa için çizim işleçleri) ve yazı tipi programlarıdır (gömülü glif anahatları). Her ikisi de iyi sıkıştırılır; bu nedenle en etkili boyut denetimi, bunları FlateDecode ile sıkıştırmaktır. FlateDecode, zlib ile sarılmış bir DEFLATE akışının PDF 2.0’daki adıdır (ISO 32000-2:2020 §7.4.4) ve NextPDF’in ürettiği filtredir.
Yazıcı, DEFLATE sıkıştırma düzeyini NextPDF\Writer\PinnedZlibCompressor aracılığıyla RFC 1951 üst sınırı olan 9’a sabitler. Düzey 9, en küçük akışlar karşılığında biraz daha fazla CPU kullanır. Düzeyi sabitlemek çıktıyı da deterministik tutar, çünkü zlib başlığı düzeyi kodlar ve değişken bir düzey baytları değiştirir. Düzeyi siz seçmezsiniz — motor bunu sabitler, böylece aynı girdiyle yapılan iki çalıştırma bayt düzeyinde özdeş akışlar üretir.
İkinci kaldıraç, yazı tipi alt küme oluşturmadır. Diskteki bir yazı tipi dosyası, yazı karakterinin tanımladığı tüm glifleri içerir, ancak “Invoice 2026” yazdıran bir belgenin bunlardan yalnızca birkaçına ihtiyacı vardır. NextPDF\Typography\FontSubsetter (TrueType için) ve NextPDF\Typography\CffSubsetter (CFF / OpenType için) belgenin gerçekte işlediği kod noktalarının üzerinden geçer, bileşik glif bağımlılıklarını çözer ve yalnızca gerekli yazı tipi tablolarını yeniden oluşturur. Bu bileşenler, deterministik altı harfli bir alt küme önek etiketi taşıyan geçerli bir alt küme yazı tipi ikili dosyası üretir (ISO 32000-2:2020 §9.9). Yazıcı bunu, gömülü bir yazı tipinin kullanılan glif kümesi bilindiği her durumda uygular, ardından alt kümeyi FlateDecode ile sıkıştırır. Belirli bir yazı tipinde alt küme oluşturma yüzde ondan az tasarruf sağlayacaksa, alt küme oluşturucu bunun yerine özgün programı döndürür, çünkü yeniden oluşturma maliyeti marjinal bir kazanca değmez.
Çıkarılacak sonuç: PDF’leri küçük tutmak için sıkıştırmayı açık bırakırsınız (varsayılan) ve gerçek yazı tipi dosyaları gömersiniz (böylece alt küme oluşturmanın küçültecek bir şeyi olur); bunu uzun bir seçenek listesine ince ayar yaparak yapmazsınız.
API yüzeyi
“API yüzeyi” başlıklı bölümAyarlayabileceğiniz tek boyut denetimi yapılandırma nesnesindedir.
NextPDF\Core\Config, türlenmiş wither yöntemlerine sahip, değişmez bir final readonly değer nesnesidir. Boyutla ilgili üye şudur:
compress(bool, varsayılantrue) — FlateDecode sıkıştırmasını etkinleştirir. Bu değeriwithCompress(bool $compress): selfile ayarlayın; bu yöntem, bayrağı değiştirilmiş ve diğer tüm alanları korunmuş yeni birConfigdöndürür.
Oluşturma sırasında belgeye bir Config sağlayın:
NextPDF\Core\Document::createStandalone(?Config $config = null): self,Configayarınızı uygulayarak bir CLI betiği ya da kısa ömürlü bir süreç için geçici kayıt defterleri kullanan bir belge oluşturur.
İki üye, boyut kaldıraçlarının üzerinde çalışacağı girdiyi şekillendirir, ancak hiçbiri kendi başına bir sıkıştırma denetimi değildir:
imageCacheBytes(int, varsayılan52_428_800) bellek içi görüntü önbelleğine üst sınır koyar vewithImageCacheBytes(int $bytes): selfbunu değiştirir. Bu değer, derleme sırasında tepe bellek kullanımını sınırlar. Gömdüğünüz görüntüleri yeniden örneklemez, yeniden sıkıştırmaz veya başka bir şekilde küçültmez — bu bir bellek tavanıdır, bir çıktı boyutu denetimi değildir.fontsDirectory(string) vewithFontsDirectory(string $dir): self, yazı tipi dosyaları için varsayılan arama yolunu ayarlar ve bu yol alt küme oluşturma akışını besler.
Yazı tipi işlemleri, belgedeki tipografi yüzeyi üzerinden gerçekleşir:
setFont(string $family, string $style = '', float $size = 12.0): staticbir yazı tipi seçer. Yazı tipi ailesi gömülebilir bir yazı tipi dosyasına çözümlendiğinde, yazıcı işlediğiniz kod noktalarını kaydeder; böylece kaydetme sırasında o yazı tipinin alt kümesini oluşturabilir.addFontDirectory(string $directory): static, yazı tipi dosyalarının aranacağı ek bir dizini kaydeder.
Çıktı için standart üçlü şudur: getPdfData(): string baytları döndürür, save(string $path): void bunları atomik olarak yazar ve output(?string $filename, OutputDestination $dest): string HTTP teslimini işler.
Alt küme oluşturma için genel bir yöntem veya bayrak yoktur. Bu, bir yazı tipi gömmenin ve metin işlemenin doğal sonucudur. Yazıcı, sizin için FontSubsetter / CffSubsetter öğesini NextPDF\Writer\PdfFontWriter içinde çalıştırır.
Kod örneği — Hızlı başlangıç
“Kod örneği — Hızlı başlangıç” başlıklı bölümBu örnek, sıkıştırmanın açıkça etkinleştirildiği ve gömülü, alt küme oluşturulmuş bir yazı tipi kullanan bir belge oluşturur, ardından baytları yazar. Çağrı biçimini net tutmak için hata işlemeyi dışarıda bırakır. Aşağıdaki üretim örneği tüm korumaları ekler.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;
// compress defaults to true; setting it explicitly documents intent.$config = (new Config())->withCompress(true);
$doc = Document::createStandalone($config);$doc->addFontDirectory(__DIR__ . '/fonts');$doc->addPage();
// Selecting an embeddable face records the glyphs used, so the writer// subsets this font automatically when the document is built.$doc->setFont('LiberationSans', '', 12);$doc->cell(0, 10, 'Invoice 2026 - subsetted, compressed output.', newLine: true);
$pdf = $doc->getPdfData();
file_put_contents(__DIR__ . '/small.pdf', $pdf);
printf("Wrote %d bytes.\n", strlen($pdf));Kod örneği — Üretim
“Kod örneği — Üretim” başlıklı bölümBu, kendi kendine yeten bir programdır. Sıkıştırma açıkken bir belge oluşturur, sizin denetlediğiniz bir dizinden bir yazı tipi gömer, alt küme oluşturucunun kullanılan glif kümesini görebilmesi için metin işler ve sonucu atomik olarak yazar. Derleme ve kaydetme yollarının fırlattığı en özgül NextPDF özel durumlarını yakalar, ardından her birini yutmak yerine bağlam ekleyerek yeniden fırlatır. NEXTPDF_FONT_DIR değerini, gömme lisansına sahip olduğunuz bir TrueType veya CFF yazı tipini içeren bir dizine yönlendirin; program gömmeden önce yolu doğrular.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;use NextPDF\Exception\CompressionException;use NextPDF\Exception\InvalidConfigException;
/** * Resolve and validate the font directory from a server-controlled source. * * Reading the directory from the environment keeps the path off the request * surface. The function rejects a missing or unreadable directory so the * embedding path never runs against untrusted or absent input. */function resolveFontDirectory(): string{ $configured = getenv('NEXTPDF_FONT_DIR'); $dir = $configured !== false && $configured !== '' ? $configured : __DIR__ . '/fonts';
$real = realpath($dir); if ($real === false || !is_dir($real) || !is_readable($real)) { throw new RuntimeException(sprintf('Font directory "%s" is not a readable directory.', $dir)); }
return $real;}
/** * Build a compressed, font-subsetted document and return its bytes. * * @param non-empty-string $fontDirectory Validated directory of embeddable fonts. * * @return string Raw PDF bytes. */function buildCompactPdf(string $fontDirectory): string{ // compress is true by default; pin it so the intent is explicit and the // streaming writer path honours it regardless of any wrapper defaults. $config = (new Config()) ->withCompress(true) ->withFontsDirectory($fontDirectory) // Bound the image cache so a build cannot exhaust memory. This is a // memory ceiling, not an output-size control. ->withImageCacheBytes(16 * 1024 * 1024);
$doc = Document::createStandalone($config); $doc->addFontDirectory($fontDirectory); $doc->addPage();
// Rendering with an embeddable face records the used codepoints, which the // writer turns into a font subset at build time. $doc->setFont('LiberationSans', '', 12); $doc->cell(0, 10, 'Invoice 2026', newLine: true); $doc->cell(0, 10, 'Compressed streams plus an automatic font subset.', newLine: true);
// getPdfData() triggers the build: page streams and the subset font program // are FlateDecode-compressed before the bytes are returned. return $doc->getPdfData();}
try { $fontDirectory = resolveFontDirectory(); $pdf = buildCompactPdf($fontDirectory);} catch (CompressionException $e) { // Raised if the zlib encoder hard-fails while compressing a stream. throw new RuntimeException( sprintf('Compression failed for a %s stream.', $e->getAlgorithm()), previous: $e, );} catch (InvalidConfigException $e) { // Raised by the output path for an invalid destination configuration. throw new RuntimeException( sprintf('Output configuration "%s" was rejected.', $e->getConfigKey()), previous: $e, );}
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$path = $out !== false && $out !== '' ? $out : __DIR__ . '/small.pdf';
if (file_put_contents($path, $pdf) === false) { throw new RuntimeException(sprintf('Could not write PDF to "%s".', $path));}
printf("Wrote %d bytes to %s.\n", strlen($pdf), $path);Beklenen STDOUT (bayt sayısı yazı tipine ve derlemeye göre değişir):
Wrote <n> bytes to <path>.Uç durumlar ve dikkat edilecek noktalar
“Uç durumlar ve dikkat edilecek noktalar” başlıklı bölüm- Sıkıştırma varsayılan olarak açıktır. Yeni bir
Configöğesindecompress,trueolarak ayarlıdır.withCompress()yöntemine nadiren gereksinim duyarsınız. Bu değeri yalnızca amacı belgelemek için ya da ham akışları okumak istediğiniz bir hata ayıklama derlemesinde devre dışı bırakmak için açıkça ayarlayın. - Sıkıştırmayı kapatmak dosyaları küçültmez, büyütür.
withCompress(false), sıkıştırılmamış akışları incelemek için bir tanılama yardımcısıdır. Hiçbir zaman bir boyut iyileştirmesi değildir. Sıkıştırma açıkken yayınlayın. - Alt küme oluşturma, gerçek bir gömülü yazı tipine gereksinim duyar. Base14 standart yazı tiplerine (Helvetica, Times, Courier ve bunların türevleri) adlarıyla başvurulur ve düz bir belgede gömülü program taşımazlar, dolayısıyla alt kümesi oluşturulacak bir şey yoktur. Alt küme oluşturma yalnızca bir yazı tipi dosyasından gömdüğünüz yazı tiplerini küçültür.
- Alt küme oluşturma otomatik ve sessizdir. Bayrak, yöntem veya onay adımı yoktur. Bir yazı tipi gömdüyseniz ve bu yazı tipiyle metin işlediyseniz, yazıcı onun alt kümesini oluşturmuştur. Gömülü program, altı harfli bir alt küme önek etiketi taşır (örneğin
ABCDEF+LiberationSans), böylece bir okuyucu bir alt kümeyi tam bir gömmeden ayırt edebilir. - Küçük bir tasarruf, tam yazı tipini korur. Bir alt küme, program boyutunda yüzde ondan az tasarruf sağlayacaksa, alt küme oluşturucu özgün dosyayı döndürür. Bu, bilinçli bir alt sınırdır: yeniden oluşturma maliyeti marjinal bir kazanca değmez. Zaten çok küçük olan bir yazı tipini gömmek ya da gliflerinin neredeyse tümünü işlemek, bu duruma yol açabilir.
imageCacheBytesbir görüntü boyutu denetimi değildir. Çıktı baytlarına değil, belleğe üst sınır koyar. NextPDF Core kendisine verdiğiniz görüntü verisini gömer; yeniden örnekleme, alt örnekleme veya yeniden kodlama adımı yoktur. Daha küçük görüntülere gereksiniminiz varsa, gömmeden önce bunları yeniden boyutlandırıp yeniden kodlayın.- Nesne akışı veya yinelenenleri kaldırma ayarı yoktur. NextPDF Core, PDF 2.0 nesne akışları veya kaynak yinelenenlerini kaldırma için bir düğme sunmaz. Böyle bir ayar aramayın — boyut kaldıraçları akış sıkıştırması ve yazı tipi alt küme oluşturmadır.
Performans
“Performans” başlıklı bölümDüzey 9’da sıkıştırma, bir akış yazmanın baskın CPU maliyetidir. En küçük çıktı karşılığında derleme süresinin birkaç yüzde puanını harcar. Maliyet, sıkıştırılmamış bayt sayısıyla doğrusaldır; bu nedenle sayfa sayısı ve gömülü yazı tipi verisi miktarı bütçeyi belirler. Alt küme oluşturma, gömülü her yazı tipi için, yazı tipinin tablo dizinini ayrıştıran, kullanılan glif kapanışını çözen ve gerekli tabloları yeniden oluşturan tek seferlik bir geçiş ekler. Büyük bir CJK yazı tipi için bu, iki kaldıraç arasında daha pahalı olanıdır, ancak sayfa başına bir kez değil, yazı tipi başına bir kez çalışır. Yüzde onluk tasarruf alt sınırı, kısmen, getirisi olmayacağı durumlarda o geçişi sıcak yoldan uzak tutmak için vardır. Tek bir gömülü alt küme içeren küçük bir belge, 1500 ms duvar süresi ve 96 MB tepe bellek bütçesine rahatça sığar. imageCacheBytes değerini gerçek tavanınıza sınırlayın; böylece birçok görüntü gömen bir derleme takas alanına düşmek yerine bellekte hızlıca başarısız olur.
Güvenlik notları
“Güvenlik notları” başlıklı bölümDerleme süreç içinde çalışır; hiçbir belge baytı ana makineden ayrılmaz ve hiçbir ağ çağrısı yapılmaz. Dışarıdan sağlanan her yazı tipini veya görüntüyü güvenilmeyen girdi olarak ele alın:
- Yazı tipi dizinini doğrulayın. Üretim örneği, yazı tipi yolunu sunucu tarafından denetlenen bir ortam değişkeninden okur ve gömmeden önce eksik veya okunamayan bir dizini reddeder. Bir yazı tipi yolunu hiçbir zaman bir istek alanından türetmeyin.
- Yalnızca yeniden dağıtım lisansına sahip olduğunuz yazı tiplerini gömün. Bir alt küme yine de gömülü bir yazı tipi programıdır. Yazı tipini taşıyan bir belgeyi yayınlamadan önce lisansın gömmeye izin verdiğini doğrulayın.
- Hatalı biçimlendirilmiş yazı tipleri özel durum fırlatır, sessizce bozuk çıktı üretmez. Ayrıştırılamayan bir yazı tipi dosyası
NextPDF\Exception\FontParsingExceptionfırlatır ve katı bir zlib hatasıNextPDF\Exception\CompressionExceptionfırlatır. En özgül özel durumu yakalayın ve buna göre hareket edin. Derlemeyi hiçbir zaman boş bircatchiçine sarmayın. - Kullanıcı girdisini hiçbir zaman çıktı yoluna eklemeyin. Örnek, sabit bir yola ya da sunucu tarafından denetlenen bir yan kanala yazar ve
save()içindeki atomik yazıcı aracılığıyla akış sarmalayıcılarını ve boş baytları reddeder. Yol geçişini önlemek için çıktı yollarını sunucu tarafından denetlenen değerlerden türetin. - Belgede gizli bilgi bulunmaz. Bir istemciye döndürdüğünüz oluşturulmuş bir belgeye kimlik bilgileri, belirteçler veya iç tanımlayıcılar gömmeyin.
Uygunluk
“Uygunluk” başlıklı bölümBu tarif kendi başına normatif bir standart iddiasında bulunmaz. Kullandığı mekanizmalar PDF 2.0 belirtimi tarafından tanımlanır: FlateDecode akış sıkıştırması (ISO 32000-2:2020 §7.4.4) ve altı karakterli bir alt küme önekiyle yazı tipi alt küme adlandırması (ISO 32000-2:2020 §9.9). NextPDF her ikisini de standart yazma yolunun bir parçası olarak üretir; bunları compress bayrağının ötesinde yapılandırmazsınız. Bu sayfanın bildirdiği structural yeniden üretilebilirlik profili, yazıcının DEFLATE düzeyini sabitlediğini yansıtır; dolayısıyla sıkıştırılmış akışlar deterministiktir, ancak deterministik ayarları da yapılandırmadıkça belge düzeyindeki tanımlayıcılar çalıştırmalar arasında yine de değişebilir. Alt küme oluşturmanın arkasındaki gömme mekanikleri için aşağıda bağlantısı verilen gömme-ve-alt-küme tarifine bakın.
Ayrıca bakın
“Ayrıca bakın” başlıklı bölüm- Bir TrueType yazı tipini gömme ve alt kümesini oluşturma — bir yazı tipi kaydedin, onunla işleyin ve gömülü alt küme etiketini inceleyin.
- Metin ve yazı tipleri oluşturma — alt küme oluşturma yolunu besleyen daha geniş metin ve yazı tipi düzenleme yüzeyi.
- Yapılandırma modülü başvurusu — tam
Configdeğer nesnesi, wither yöntemleri ve bunların varsayılanları. - Özel durum bilinçli hata işleme —
CompressionException,FontParsingExceptionveInvalidConfigExceptionarkasındaki NextPDF özel durum hiyerarşisi.