Harici PDF'leri birleştirin veya mevcut belgelerden sayfalar ekleyin
Bir bakışta
“Bir bakışta” başlıklı bölümDiskte birkaç PDF dosyanız var ve tek bir PDF’ye ihtiyacınız var. Bu tarif, mevcut belgeleri Core birleştirme yüzeyi olan NextPDF\Document\PdfMerger ile uçtan uca birleştirir. Ham PDF bayt dizeleri sağlarsınız. Birleştirici, çakışmaları önlemek için her nesneyi yeniden numaralandırır, tek bir sayfa ağacı ve tek bir çapraz başvuru tablosu oluşturur ve diske yazabileceğiniz ya da bir istemciye akış olarak gönderebileceğiniz bir NextPDF\Document\MergeResult döndürür.
Aynı yüzey, en sık ihtiyaç duyduğunuz üç görevi kapsar:
- Birleştirin — sıralı bir PDF listesini tek bir belgede bir araya getirmek.
- Ekleyin — bir temel PDF’nin sonuna ikinci bir PDF eklemek.
- Başa ekleyin — yeni belgeyi girdi sırasının en başına koymak.
Birleştirme, headless tarayıcıya veya ağ çağrısına gerek kalmadan süreç içinde çalışır. Core’un kurulu olması (composer require nextpdf/core:^3) ve okunabilir iki veya daha fazla PDF dosyası gerekir.
Kurulum
“Kurulum” başlıklı bölümcomposer require nextpdf/core:^3Kavramsal genel bakış
“Kavramsal genel bakış” başlıklı bölümBir PDF, sayfaları, kökü bir /Pages düğümü olan bir sayfa ağacında düzenler ve her dolaylı nesneyi bir çapraz başvuru tablosu aracılığıyla bulur. İki kaynak belgeyi birleştirdiğinizde nesne numaraları çakışır. Her iki dosya da neredeyse her zaman bir 1 0 obj nesnesi, bir /Catalog ve bir /Pages düğümü içerir. Baytları yalnızca uç uca eklerseniz, başvurular artık tanımladıkları nesnelere işaret etmediği için bozuk bir dosya üretirsiniz.
PdfMerger bu çakışmayı çözer. Her girdiden sayfa nesnelerini çıkarır, her nesneyi tek bir adres alanı içinde yeniden numaralandırır, her sayfanın /Parent başvurusunu birleştirilmiş tek bir /Pages düğümüne işaret edecek şekilde yeniden yazar ve tek bir katalog, tek bir sayfa ağacı ve tek bir treyler üretir. Çıktı, uç uca eklenmiş bir birleştirme değil, yapısal olarak yeni bir belgedir.
Sıralama kuralı basittir: sayfalar, girdi listesindeki kaynak dosyalarla aynı sırada görünür. Sona eklemek için temel belgeyi en başa koyun. Başa eklemek için yeni belgeyi en başa koyun. Ayrı bir başa ekleme yöntemi yoktur, çünkü gereken tek denetim girdi sırasıdır.
API yüzeyi
“API yüzeyi” başlıklı bölümnew NextPDF\Document\PdfMerger() iki yöntem sunar.
merge(list<string> $pdfFiles, int $maxFiles = 100, int $maxTotalBytes = 200_000_000): MergeResult, ham PDF bayt dizelerinden oluşan sıralı bir listeyi birleştirir. İki sınır parametresi, dosya sayısına ve toplam girdi boyutuna üst sınır getirir. Her ikisi de varsayılan olarak güvenli üretim değerlerine ayarlıdır; bunları her iş yükü için daraltın.append(string $basePdf, string $appendPdf): MergeResult, tam olarak iki belgeyi bu sırayla birleştiren kullanışlı bir sarmalayıcıdır.merge([$basePdf, $appendPdf])ile eşdeğerdir.
Her iki yöntem de bir NextPDF\Document\MergeResult döndürür; bu readonly nesne, $pdfData (birleştirilmiş baytlar), $totalPages, $sourceCount, $mergedSize değerlerini ve isValid() yardımcısını içerir. Bu yardımcı, çıktının %PDF başlığıyla başladığını doğrular.
Girdiler, dosya yolları değil, ham bayt dizeleridir. Dosyayı file_get_contents() ile kendiniz okuyun ya da baytları nesne depolamadan alın. Bu, birleştiriciyi dosya sistemi varsayımlarından bağımsız tutar ve diske hiç dokunmayan belgeleri birleştirmenize olanak tanır.
Harici bir PDF’den tek bir sayfayı yeniden kullanılabilir bir Form XObject olarak içe aktarmanız gerekiyorsa (örneğin, oluşturulan içeriğin arkasına bir antetli kağıt sayfası basmak için) paketler arası içe aktarıcı sözleşmesi olan NextPDF\Contracts\ImportedFormObjectInterface öğesini kullanın; bu sözleşme nextpdf/artisan gibi içe aktarıcılar tarafından uygulanır. Tüm belge ve tüm sayfa düzeyindeki birleştirmeler için burada belgelenen PdfMerger yüzeyini kullanın.
Kod örneği — hızlı başlangıç
“Kod örneği — hızlı başlangıç” başlıklı bölümBu örnek, iki dosyayı okur ve birleştirilmiş çıktıyı yazar. Çağrının yapısını göstermek için hata işlemeyi kapsam dışında bırakır; aşağıdaki üretim örneği eksiksiz korumaları ekler.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Document\PdfMerger;
$merger = new PdfMerger();
$result = $merger->merge([ file_get_contents(__DIR__ . '/cover.pdf'), file_get_contents(__DIR__ . '/body.pdf'), file_get_contents(__DIR__ . '/appendix.pdf'),]);
file_put_contents(__DIR__ . '/combined.pdf', $result->pdfData);
printf("Merged %d source(s) into %d page(s).\n", $result->sourceCount, $result->totalPages);Kod örneği — üretim
“Kod örneği — üretim” başlıklı bölümBu bağımsız program, bellekte iki küçük belge oluşturur; böylece harici bir dosya olmadan çalışır. Bunları birleştirir, sonucu doğrular ve çıktıyı yazar. Birleştirme yüzeyinin oluşturduğu iki istisnayı yakalar ve her birini yutmak yerine bağlam ekleyerek yeniden fırlatır. Bellek içi girdileri kendi file_get_contents() okumalarınızla veya nesne depolamadan yaptığınız okuma işlemleriyle değiştirin ve çıktıyı yanıtınıza ya da depolama katmanınıza yönlendirin.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;use NextPDF\Document\MergeResult;use NextPDF\Document\PdfMerger;use NextPDF\Exception\PageLayoutException;use NextPDF\Exception\WriterException;
/** * Build a tiny labelled PDF so the program is self-contained. * * In your own code, replace calls to this helper with reads of the external * PDFs you want to combine, for example file_get_contents($path). */function buildSample(string $label, int $pages): string{ $doc = Document::createStandalone(); $doc->setTitle($label);
for ($page = 1; $page <= $pages; $page++) { $doc->addPage(); $doc->setFont('helvetica', '', 12); $doc->cell(0, 10, sprintf('%s - page %d', $label, $page), newLine: true); }
return $doc->getPdfData();}
// Validate the input set before touching the merger. An empty set is a// configuration error, not an empty success./** @var list<string> $sources Raw PDF byte strings, in output order. */$sources = [ buildSample('Cover', 1), // first in the list -> first in the output (prepend position) buildSample('Body', 2), buildSample('Appendix', 1), // last in the list -> appended after the body];
if ($sources === []) { throw new RuntimeException('No source PDFs supplied to merge.');}
$merger = new PdfMerger();
try { // Bound the merge deliberately: at most 50 files, 100 MB total input. $result = $merger->merge($sources, maxFiles: 50, maxTotalBytes: 100_000_000);} catch (PageLayoutException $e) { // Raised when the list is empty or an input does not begin with %PDF. throw new RuntimeException( sprintf('Merge rejected an input: %s', $e->getConstraint()), previous: $e, );} catch (WriterException $e) { // Raised when the total input size exceeds the configured byte cap. throw new RuntimeException( sprintf('Merge exceeded its size budget at stage "%s".', $e->getWriterState()), previous: $e, );}
if (!$result->isValid()) { throw new RuntimeException('Merged output failed its structural header check.');}
emitResult($result);
/** * Write the merged document to the cookbook side-channel, or to a default file. */function emitResult(MergeResult $result): void{ printf( "Merged %d source(s) into %d page(s), %d bytes.\n", $result->sourceCount, $result->totalPages, $result->mergedSize, );
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT'); $path = $out !== false && $out !== '' ? $out : __DIR__ . '/combined.pdf';
if (file_put_contents($path, $result->pdfData) === false) { throw new RuntimeException(sprintf('Could not write merged PDF to "%s".', $path)); }}Beklenen standart çıktı (sayfa toplamı kaynak sayfa sayılarının toplamıdır ve bayt boyutu oluşturma işlemine bağlıdır):
Merged 3 source(s) into 4 page(s), <n> bytes.Uç durumlar ve dikkat edilecek noktalar
“Uç durumlar ve dikkat edilecek noktalar” başlıklı bölüm- Girdiler yol değil, bayt dizeleridir.
merge()ham PDF dizeleri alır. Önce dosyayıfile_get_contents()ile okuyun. Bir yol dizesi iletmek, girdinin%PDFbaşlık denetiminden geçememesine yol açar vePageLayoutExceptionoluşturur. - Sıra, çıktı sırasıdır. Sayfalar, kaynak dosyalarının listede göründüğü sırayla yerleşir. Başa ekleme yöntemi yoktur: başa eklemek için yeni belgeyi en başa, sona eklemek için en sona koyun.
- Boş liste bir hatadır. Boş bir
$pdfFiles, boş bir sonuç üretmez;PageLayoutExceptionoluşturur. Birleştiriciyi çağırmadan önce listeyi doğrulayın. - Her girdi baştan doğrulanır. Her girdi boş olmamalı ve
%PDFile başlamalıdır. Başarısız olan ilk girdi, ihlal edilen kısıtlamayla birliktePageLayoutExceptionoluşturur ve hiçbir şey birleştirilmez. - Sınırlar kırpma yapmaz, istisna oluşturur.
maxFilesdeğerinin aşılması dahili kaynak koruması üzerinden istisna oluşturur vemaxTotalBytesdeğerinin aşılmasıWriterExceptionoluşturur. Birleştirici hiçbir zaman sessizce dosya düşürmez veya bayt kırpmaz, bu nedenle her iki sınırı da iş yükünüze göre ayarlayın. - Çıktı, bayt düzeyinde kararlı değil, yapısal olarak yenidir. Birleştirilmiş belge yeni bir katalog, sayfa ağacı ve treyler taşır. Aynı girdilerle yapılan iki çalıştırma yapısal olarak eşittir, ancak bayt düzeyinde özdeş olacakları garanti edilmez. Bu tarifin
structuralbir yeniden üretilebilirlik profili bildirmesinin nedeni budur. - Sayfa düzeyindeki açıklamalar ve paylaşılan kaynaklar. Birleştirme, sayfa nesnelerini tek bir ağaçta bir araya getirir. Bir kaynak dosyada sayfa nesnelerinin dışında bulunan belge düzeyindeki yapılar aktarılmaz. Tek bir sayfayı kaynaklarıyla birlikte yeniden kullanılabilir bir grafik olarak içe aktarmanız gerektiğinde,
ImportedFormObjectInterfaceyolununextpdf/artisangibi bir içe aktarıcı aracılığıyla kullanın.
Performans
“Performans” başlıklı bölümBirleştirme, toplam sayfa sayısıyla doğrusaldır. İşin büyük kısmı, birleştiricinin kendi kayıt tutma işlemlerinden değil, ayrıştırma ve nesneleri yeniden numaralandırma işlemlerinden kaynaklanır. Çıktı oluşturulurken her kaynak bellekte dize olarak tutulduğu için en yüksek bellek kullanımı toplam girdi baytlarıyla birlikte artar. maxTotalBytes koruması bu en yüksek değeri sınırlı tutar. Yüksek hacimli işlem hatları için, hatalı biçimlendirilmiş veya aşırı büyük bir grubun belleği tüketmek yerine hızlıca başarısız olması amacıyla maxFiles ve maxTotalBytes değerlerini iş yükünüzün ihtiyaç duyduğu en küçük değerlere ayarlayın. Tipik bir küçük birleştirme, 1500 ms wall-clock süresi ve 64 MB en yüksek bellek bütçesi içinde kalır.
Güvenlik notları
“Güvenlik notları” başlıklı bölümBirleştirme süreç içinde çalışır; hiçbir belge baytı ana makineden ayrılmaz ve hiçbir ağ çağrısı yapılmaz. Her harici PDF’yi güvenilmeyen girdi olarak değerlendirin:
- Sınırları dar tutun.
maxFilesvemaxTotalBytes, hizmet engelleme amaçlı girdilere karşı ilk savunma hattınızdır. Karşıya yükleme kabul eden herhangi bir yüzey için bunları cömert varsayılanlara değil, gerçek üst sınırınıza ayarlayın. - Güvenmeden önce doğrulayın. Başarılı bir birleştirme, baytların birleştirildiği anlamına gelir; girdilerin güvenli olduğu anlamına gelmez. Güvenilmeyen girdileri önce Core denetleyicisinden geçirin. Daha ağır işlemeden önce şifrelemeyi, imzaları ve risk işaretçilerini belirleyen sınırlı bir önceliklendirme taraması için Bir PDF’yi ayrıştırma ve inceleme sayfasına bakın.
- Kullanıcı girdisini asla bir yola yerleştirmeyin. Bu tarif, sabit bir yola veya Cookbook yan kanalına yazar. Dizin geçişini önlemek için çıktı yollarını bir istek alanından değil, sunucu denetimli değerlerden türetin.
- Belgede gizli bilgi bulundurmayın. Bir istemciye döndürdüğünüz birleştirilmiş bir belgeye kimlik bilgileri, belirteçler veya dahili tanımlayıcılar gömmeyin.
Uyumluluk
“Uyumluluk” başlıklı bölümBu tarif, kendi başına hiçbir normatif standart iddiasında bulunmaz. Mevcut belgeleri Core birleştirme yüzeyi aracılığıyla bir araya getirir ve sonucu MergeResult::isValid() başlık denetimiyle doğrular. PdfMerger tarafından yeniden oluşturulan sayfa ağacı modeli, /modules/core/document/ başvurusunda açıklanan PDF 2.0 sayfa ağacı yapısıdır. Sürüm, sayfa sayısı, şifreleme ve imza bayrakları dahil olmak üzere herhangi bir girdi veya çıktı belgesini yapısal olarak okumak için Bir PDF’yi ayrıştırma ve inceleme sayfasında belgelenen Core denetleyicisini kullanın.
Ayrıca bakın
“Ayrıca bakın” başlıklı bölüm- Document modülü başvurusu — eksiksiz bölme, birleştirme ve belge bölümü yüzeyi.
- Bir PDF’yi ayrıştırma ve inceleme — güvenilmeyen girdileri birleştirmeden önce önceliklendirme taramasından geçirin.
- İstisna bilinçli hata işleme — NextPDF istisna hiyerarşisinin
PageLayoutExceptionveWriterExceptioniçin nasıl çalıştığı. - Çok sayfalı bir belge oluşturma — daha sonra birleştireceğiniz sayfaları yazın.