Przejdź do głównej zawartości

Rozwiązywanie problemów z pakietem NextPDF dla Laravela

Ta strona pomaga powiązać każdą widoczną awarię pakietu ze zweryfikowaną przyczyną źródłową w kodzie. Każdy wpis zawiera objaw, przyczynę i rozwiązanie.

Okno terminala
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

Większość zgłaszanych problemów mieści się w jednej z pięciu grup: wykrywanie, rozstrzyganie w kontenerze, podpisywanie, zadania w kolejce oraz nazwy plików w protokole Hypertext Transfer Protocol (HTTP). Pakiet celowo zgłasza błędy jawnie. Nieskonfigurowane funkcje opcjonalne zwracają null, a niebezpieczne dane wejściowe powodują zgłoszenie typowanych wyjątków. Objaw zwykle prowadzi bezpośrednio do przyczyny.

ObjawZweryfikowana przyczynaRozwiązanie
Dostawca usług nie jest zarejestrowany po instalacjiAplikacja wyłącza wykrywanie za pomocą extra.laravel.dont-discoverUsuń pakiet z dont-discover albo zarejestruj NextPdfServiceProvider ręcznie w bootstrap/providers.php
config('nextpdf') jest pusteKonfiguracja nie została scalona, ponieważ nie rozstrzygnięto żadnego zadeklarowanego wiązania (dostawca odroczony)Rozstrzygnij dowolny wpis provides() lub potwierdź wykrywanie poleceniem php artisan package:discover --ansi
Plik config/nextpdf.php nie został utworzony podczas publikowaniaUżyto niezgodnego znacznika publikowaniaUżyj dokładnie tego znacznika: php artisan vendor:publish --tag=nextpdf-config
RuntimeException: „NextPDF requires the ext-mbstring/ext-zlib PHP extension”W środowisku uruchomieniowym brakuje jednego z wymaganych rozszerzeń Hypertext Preprocessor (PHP)Zainstaluj lub włącz mbstring oraz zlib w php.ini
ObjawZweryfikowana przyczynaRozwiązanie
app(SignerInterface::class) zwraca nullPodpisywanie jest wyłączone albo certyfikat w nextpdf.signature jest pustyUstaw signature.enabled = true oraz prawidłowy signature.certificate; zainstaluj nextpdf/premium, aby udostępnić konkretną implementację podpisującego
app(TsaClient::class) zwraca nullnextpdf.tsa.url jest pusteSkonfiguruj tsa.url (oraz credentials/pins, jeśli są potrzebne)
Nie znaleziono klasy dla typu wersji PDF/Anextpdf.pdfa nie jest null, ale nextpdf/premium nie jest zainstalowanyZainstaluj nextpdf/premium lub przywróć pdfa do wartości null
Nie znaleziono klasy podczas rozstrzygania kontraktu e-fakturyWiązania są zarejestrowane, ale brakuje konkretnych implementacji PremiumZainstaluj nextpdf/premium; kontrakty e-faktury są rozstrzygane leniwie, więc bez Premium błąd pojawia się dopiero przy pierwszym rozstrzygnięciu
Ten sam dokument został zmodyfikowany w dwóch logicznych operacjachWiązanie dokumentu jest fabryką; jedna rozstrzygnięta instancja została użyta ponownieRozstrzygaj nowy PdfDocumentInterface dla każdego dokumentu

Gdy w kontenerze brakuje danego wpisu, wywołanie get() zgłasza wyjątek not-found (PHP Standard Recommendation 11 (PSR-11) §1.1.2). Kontrakty e-faktury są powiązane, więc metoda has() kontenera zwraca true. Brak konkretnej implementacji Premium zgłasza błąd dopiero podczas konstrukcji, a nie na poziomie samego kontenera.

ObjawZweryfikowana przyczynaRozwiązanie
InvalidArgumentException: Path traversal sequences are not allowedŚcieżka wyjściowa zawiera segment ..Użyj ścieżki bezwzględnej bez sekwencji przejścia, wewnątrz katalogu przechowywania
InvalidArgumentException: Stream wrappers are not allowedŚcieżka używa schematu, takiego jak php://Użyj zwykłej ścieżki systemu plików
InvalidArgumentException: Output path contains null bytesŚcieżka zawiera bajt \0Oczyść ścieżkę przed wysłaniem zadania
InvalidArgumentException: Output path must end with .pdf extensionŚcieżka nie kończy się na .pdf (bez rozróżniania wielkości liter)Użyj rozszerzenia .pdf (lub .PDF)
Zadanie wykonuje się, ale plik jest pusty lub nieprawidłowyDomknięcie konstruktora nie zwróciło skonfigurowanego dokumentuZwróć dokument z konstruktora; zadanie zapisuje zwróconą wartość
Zadanie używa niewłaściwej kolejki lub limitu czasunextpdf.queue.* nie jest ustawione zgodnie z oczekiwaniamiUstaw queue.queue, queue.connection oraz queue.timeout; tries i backoff wymagają utworzenia podklasy

Sprawdzanie ścieżki odbywa się wewnątrz handle() w procesie roboczym, więc nieprawidłowa ścieżka powoduje błąd podczas wykonywania, a nie przy wysyłaniu zadania. Jest to zamierzone: proces roboczy weryfikuje zserializowany ładunek kolejki tam, gdzie go przetwarza.

ObjawZweryfikowana przyczynaRozwiązanie
Nazwa pobieranego pliku ma niespodziewanie wartość document.pdfPrzekazano pustą nazwę pliku; fabryka używa wartości domyślnejPrzekaż niepustą nazwę pliku
Nazwa pliku utraciła ścieżkę lub znaki specjalneMechanizm czyszczenia nazw plików usuwa separatory ścieżek, znaki sterujące i bajty zerowePrzekaż tylko bazową nazwę pliku; to oczekiwane zabezpieczenie
Nazwa pliku spoza ASCII w niektórych klientach wyświetla się jako krzaki (mojibake)Odpowiedź emituje Request for Comments 5987 (RFC 5987) filename*= dla nazw spoza ASCII; starsze klienty odczytują wartość zapasową w ASCIIZachowanie oczekiwane; podaj nazwę bezpieczną dla ASCII, jeśli starszy klient ma wyświetlić ją dokładnie
Odpowiedź strumieniowa nie ma nagłówka Content-LengthOdpowiedzi strumieniowe z założenia pomijają Content-Length (wyjście fragmentowane)Zachowanie oczekiwane; użyj niestrumieniowych inline()/download(), jeśli wymagany jest nagłówek długości
Okno terminala
# Confirm the provider is discovered
php artisan package:discover --ansi
# Inspect merged configuration
php artisan tinker --execute="dump(config('nextpdf.queue'));"
resource: src/Laravel/NextPdfServiceProvider.php (null-check pattern)
<?php
declare(strict_types=1);
use NextPDF\Contracts\SignerInterface;
$signer = app(SignerInterface::class);
if ($signer === null) {
// Signing not configured, or nextpdf/premium not installed.
// Continue without a signature, or fail with a clear message.
}
  • Gdy dostawca jest odroczony, świeża instalacja może wyglądać na „uszkodzoną” aż do pierwszego istotnego rozstrzygnięcia. Potraktuj pojawienie się pakietu w wyniku package:discover jako sygnał powodzenia.
  • Gdy image_cache_mb = null, pakiet przyjmuje wartość zapasową 50 MB; tylko 0 wyłącza pamięć podręczną. Zgłoszenie „pamięć podręczna się nie wyłącza” zwykle oznaczało użycie null.
  • Gdy signature.level = null, pakiet niejawnie przyjmuje wartość zapasową PDF Advanced Electronic Signatures (PAdES) B-B. Zgłoszenie „nieoczekiwany B-B” zwykle oznaczało, że poziom pozostawiono nieustawiony.

Jeśli pierwsze żądania w długo działającym procesie roboczym są wolne, oznacza to, że rejestr czcionek analizuje dane na żądanie. Wypełnij nextpdf.preload_fonts, aby rozgrzewka wykonała się jeden raz przy uruchomieniu procesu roboczego. Szczegóły znajdziesz w /integrations/laravel/configuration/ oraz /integrations/laravel/boot-and-discovery/.

Odrzucanie ścieżek i nazw plików to mechanizmy zabezpieczające, a nie błędy. Nie omijaj ich przez wstępne dekodowanie ani rozluźnianie kontroli. Zamiast tego kieruj zapis plików przez kontrolowaną ścieżkę przechowywania. Zobacz /integrations/laravel/security-and-operations/.

StwierdzenieŹródłoKlauzulareference_id
Brak wpisu w kontenerze powoduje not-found przy get()PSR-11 Container§1.1.2
  • /integrations/laravel/install/ — kroki wykrywania i publikowania
  • /integrations/laravel/configuration/ — każdy klucz i jego wartość domyślna
  • /integrations/laravel/production-usage/ — wzorce wstrzykiwania zależności (DI) i kolejek
  • /integrations/laravel/security-and-operations/ — dlaczego istnieją kontrole ścieżek