İçeriğe geç

Contracts / Streaming

Akış alanı iki experimental arabirim içerir: artımlı PDF çıktısı için StreamingWriterInterface ve sayfa düzeyinde içerik oluşturma için CursorInterface. Core, her ikisini de uygulayan deterministik ve test edilmiş bir motor sunar. Motor sınıfları iç kullanıma yöneliktir; bu nedenle motoru kendiniz uygulamak yerine genel experimental sözleşmesini kullanmanız gerekir. Katman experimental olduğundan, sözleşme önceden bir kullanımdan kaldırma bildirimiyle birlikte bir alt sürümde değişebilir. Üretimde buna bağımlı olmadan önce sürümü sıkı biçimde sabitleyin veya kendi bağdaştırıcınızın arkasına alın.

Terminal window
composer require nextpdf/core:^3

Akış yazıcısı, her sayfayı siz oluştururken serileştirir ve bir sonraki sayfa başlamadan önce çıktıya boşaltabilir. Belge mevcut bellek bütçesini aşabilecekse bunu kullanın. Bellek içi yazıcı, belgenin tamamını tutar. Akış yazıcısı tutmaz. StreamingWriterInterface katı bir durum makinesi tanımlar. Yeni bir örnek CLOSED durumundadır. open() onu OPEN durumuna geçirir ve PDF üst bilgisini çağıranın sağladığı bir akışa yazar. newPage() onu PAGING durumuna geçirir ve bir imleç döndürür. close() çapraz başvuru yapısını ve fragmanı yazar, ardından onu terminal bir CLOSED durumuna geçirir. Çapraz başvuru akışı, ISO 32000-2 §7 kapsamında olduğu gibi, her nesne numarasını bayt uzaklığıyla eşler. Her örnek için yalnızca bir oturum çalışır. close() çağrısından sonra örnek artık kullanılamaz. Akışın sahibi çağırandır. Yazıcı akışa yazar ancak onu hiçbir zaman kapatmaz.

CursorInterface sayfa düzeyindeki yazma yüzeyidir. Bir imleci StreamingWriterInterface::newPage() ile elde edersiniz ve bu imleç, siz onu sonlandırana kadar, bir sonraki newPage() onu otomatik olarak sonlandırana kadar veya close() onu geçersiz hale getirene kadar geçerli kalır. Geçersiz hale getirme kalıcıdır. Bir imleç yeniden etkinleştirilemez. Geçersiz hale getirilmiş bir imleçteki her yöntem LogicException oluşturur. İmleç ham içerik akışı işleçlerini yazar, etkin yazı tipini ayarlar ve konumlandırılmış metin yazar. Bir içerik akışı, ISO 32000-2 §8 kapsamında olduğu gibi, sayfa içeriğini bir grafik işleçleri dizisi olarak kodlar. İmleç düşük düzeyli bir yüzeydir: metin şekillendirme, çift yönlü yeniden sıralama, satır bölme veya herhangi bir yerleşim gerçekleştirmez. Bunlar Document düzeyindeki konulardır. Tek imleç değişmezi her zaman geçerlidir: herhangi bir anda en çok bir imleç geçerlidir.

Her iki arabirim de experimental olup Core bunları destekleyen bir motor sunar: deterministik bir StreamingWriterInterface uygulaması, bu uygulamanın sayfa imleci ve bellek karşılaştırması için kullanılan bir atma havuzu. Bu motor sınıfları iç kullanıma yöneliktir ve genel yüzeyin bir parçası değildir. Akışı kullanmak için experimental sözleşmesine bağımlı olun ve uygulamayı Core sağlasın. Her türün PHPDoc’u, yaşam döngüsü durum makinesi ve kapsam gerekçesi için akış yazıcı ADR belgesine işaret eder. Katman experimental olduğundan, sözleşme imzası önceden bir kullanımdan kaldırma bildirimiyle birlikte bir alt sürümde hâlâ değişebilir. Üretimde buna bağımlı olmadan önce sürümü sıkı biçimde sabitleyin veya kendi bağdaştırıcınızın arkasına alın.

TürÇeşitTemel üyelerKararlılıkŞu sürümden beri
StreamingWriterInterfacearabirimopen(resource, Config), newPage(?PageSize): CursorInterface, close()experimental (sunulan motor)3.1.0
CursorInterfacearabirimwriteContent(string), setFont(string, string, float), writeText(float, float, string), finalizePage()experimental (sunulan motor)3.1.0

open(), yazılamayan bir akış için InvalidArgumentException ve yazıcı zaten açıksa LogicException oluşturur. close() idempotent değildir. İki kez çağırmak özel durum oluşturur.

examples/contracts/streaming-quickstart.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\StreamingWriterInterface;
use NextPDF\Core\Config;
/**
* Drive a streaming writer through one page.
*
* The parameter is the experimental contract; Core supplies the
* implementation. Type-hint the interface and let the engine satisfy it.
*
* @param StreamingWriterInterface $writer A Core-supplied streaming writer.
* @param resource $stream A writable, caller-owned stream.
*/
function writeOnePage(StreamingWriterInterface $writer, $stream): void
{
$writer->open($stream, new Config());
$cursor = $writer->newPage();
$cursor->setFont('helvetica', '', 12.0);
$cursor->writeText(72.0, 720.0, 'Streamed page.');
$cursor->finalizePage();
$writer->close();
// The caller closes $stream after close() returns.
}

İşlev experimental arabirimini hedefler; bu nedenle motor sınıfından ayrık kalır. Core, çağrı noktasında çalışan uygulamayı enjekte eder.

examples/contracts/streaming-production.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\StreamingWriterInterface;
use NextPDF\Core\Config;
use NextPDF\ValueObjects\PageSize;
use Psr\Log\LoggerInterface;
final readonly class LargeReportStreamer
{
public function __construct(
private StreamingWriterInterface $writer,
private LoggerInterface $logger,
) {}
/**
* Stream a multi-page report to a caller-owned file handle.
*
* @param resource $stream Writable file handle owned by the caller.
* @param list<list<string>> $pages One list of text lines per page.
*/
public function stream($stream, array $pages): void
{
$this->writer->open($stream, new Config());
try {
foreach ($pages as $lines) {
$cursor = $this->writer->newPage(PageSize::A4());
$cursor->setFont('helvetica', '', 11.0);
$y = 760.0;
foreach ($lines as $line) {
$cursor->writeText(72.0, $y, $line);
$y -= 14.0;
}
$cursor->finalizePage();
}
} finally {
$this->writer->close();
}
}
}

Buradaki finally bloğu, sayfa döngüsünde özel durum oluşsa bile yazıcının kapanmasını ve fragmanın yazılmasını güvence altına alır. Akışın sahibi yine de çağırandır ve onu çağıran kapatır.

  • Motor sınıfına değil, arabirime bağımlı olun. Her iki sözleşmeyi de uygulayan motor iç kullanıma yöneliktir ve genel yüzeyin bir parçası değildir. Onu new ile örneklemeyin veya adıyla başvurmayın. StreamingWriterInterface için tür ipucu verin ve uygulamayı Core sağlasın.
  • Sözleşme experimental niteliğindedir. İmzası, önceden bir kullanımdan kaldırma bildirimiyle birlikte bir alt sürümde değişebilir. Üretimde buna bağımlı olmadan önce sürümü sıkı biçimde sabitleyin veya kendi bağdaştırıcınızın arkasına alın.
  • Bir imleç, bir sonraki newPage() veya close() çağrıldığı anda geçersiz olur. Eski bir imleci tutup üzerinde bir yöntem çağırmak LogicException oluşturur. Açıklık için açıkça sonlandırın.
  • close() idempotent değildir. Onu iki kez çağırmak çağıran tarafın hatasıdır, kurtarılabilir bir koşul değildir. Sözleşme özel durum oluşturur.
  • Yazıcı akışı hiçbir zaman kapatmaz. close() döndükten sonra çağıranın sahip olduğu bir tutamacı kapatmayı unutursanız bir dosya tanımlayıcısı sızdırırsınız.
  • Motor, sonlandırılan her sayfayı boşaltır; böylece yerleşik bellek sayfa sayısıyla birlikte büyümez. Tam bellek profili bir experimental katman özelliğidir ve alt sürümler arasında değişebilir. Tek bir ölçüme dayanarak bir varsayımı sabit kodlamayın.

Akış tasarımı en yüksek bellek kullanımını sınırlar. Sunulan motor, tamamlanan her sayfayı boşaltır ve tamponunu serbest bırakır; böylece yerleşik küme, bellek içi yazıcının aksine sayfa sayısıyla birlikte büyümez. Motor, süreç ayak izini neredeyse sabit tutmak için çapraz başvuru ve sayfa ağacı muhasebesini disk destekli geçici akışlara aktarır. Somut bellek ve süre değerleri bir experimental katman özelliğidir ve alt sürümler arasında değişebilir; bu nedenle bu sayfa hiçbir sabit sayı öne sürmez. 1500 ms süre ve 64 MB tepe değerinden oluşan performance_budget, tuval için bir sınır çerçevesidir; sözleşmeye bağlı bir garanti değildir. Yeniden üretilebilirlik bitwise düzeyindedir: aynı içerik ve yapılandırma, motorun altın temel testleriyle sabitlenen bayt düzeyinde özdeş çıktı üretir.

İmlecin writeContent() yöntemi düşük düzeyli bir kaçış kapısıdır. Sağlanan baytları sayfa içerik akışına olduğu gibi ekler ve işleç sözdizimini veya anlamını doğrulamaz. writeContent() yöntemine geçirilen güvenilmeyen girdi, bozuk veya kötü amaçlı bir PDF üretir. Bu yöntemi yalnızca güvenilir girdi alan bir yüzey olarak ele alın ve çağıranın etkileyebildiği herhangi bir metin için writeText() yöntemini yeğleyin. Sunulan imleç, writeText() yöntemine geçirilen metne PDF değişmez dize dil bilgisi için kaçış uygular, ancak ham işleçleri arındırmaz. Çağıranın sahip olduğu akış modeli de bir güvenlik özelliğidir. Motor akışa yazar ancak onu hiçbir zaman kapatmaz veya yeniden açmaz; bu nedenle çıktıyı yeniden yönlendiremez. Motor sunulduğundan, çalışma zamanı saldırı yüzeyi gerçektir. Çağıranlar writeContent() yöntemine asla güvenilmeyen baytlar aktarmamalı ve motor sözleşmenin değişmezlerine uymalıdır.

İddiaStandartMaddeKanıt
Bir içerik akışı, sayfa içeriğini imlecin eklediği bir grafik işleçleri dizisi olarak kodlar.ISO 32000-2§8
Yazıcı, kapanışta her nesne numarasını bayt uzaklığıyla eşleyen bir çapraz başvuru yapısı yayar.ISO 32000-2§7

Her iki madde de sözlükte sabitlenmiş ve başka sözcüklerle ifade edilmiştir. NextPDF hiçbir normatif metni yeniden üretmez. Sözleşme PHPDoc’unda başvurulan akış yazıcı ADR belgesi, yaşam döngüsünü ve kapsam gerekçesini içerir.

Açık kaynaklı Core’da, bu experimental sözleşmelerin arkasında test edilmiş bir akış motoru sunulur. Motor sınıfları iç kullanıma yöneliktir; bu nedenle akışı somut bir sınıf adı yerine genel sözleşme üzerinden kullanmanız gerekir. NextPDF Pro ve NextPDF Enterprise aynı sözleşmeyi izler; bu nedenle Core içinde StreamingWriterInterface sözleşmesine göre yazılan kod, aynı sözleşmenin bir Premium uygulamasıyla geçerli kalır. Tek uyarı sürüm veya kullanılabilirlik değil, experimental katmanıdır. İmza, önceden bir kullanımdan kaldırma bildirimiyle birlikte bir alt sürümde değişebilir.