PDF::API2 est un module perl pour la manipulation de fichiers PDF. Il peut être utilisé en combinaison avec un script CGI pour envoyer un fichier directement à un client. Quelque chose du genre :
use PDF::API2;
use CGI;
my $cgi = CGI->new;
my $pdf = new PDF::API2();
# …
print $cgi->header(-type => 'application/pdf', -Content_Disposition => 'attachment; filename=monpdf.pdf');
# Envoie le PDF sur la sortie standard (vers le client)
$pdf->saveas('-');
Le PDF ainsi généré pourra être ouvert par des lecteurs basés sur libpoppler (et peut être d'autres) mais Acrobat Reader refusera en prétendant qu'il est corrompu. En essayant de rouvrir le même PDF avec PDF::API2, celui-ci vous enverra gentiment bouler avec un Malformed xref in PDF file at /usr/share/perl5/PDF/API2/Basic/PDF/File.pm line 1198..
En fait, les sections xref des PDF utilisent des informations comprenant des déplacements dans le fichier. Pour les obtenir, PDF::API2 utilise le déplacement courant du fichier dans lequel il est en train d'écrire. Le problème est que lorsque l'on est en CGI, l'écriture des headers décale le déplacement courant de la taille de ceux-ci, les déplacement indiqués dans la XRef sont donc invalides.
Pour résoudre le problème, il suffit de modifier légèrement la génération du PDF en l'écrivant dans une chaine puis en l'affichant :
# $pdf->saveas('-');
print $pdf->stringify();
Et l'erreur disparaît, Acrobat Reader est content…