0
votes

I found many questions about which headers to use for download pdf files. Instead, I want to view them online (i.e. with the embedded Chrome plugin) and optionally download them with it.

Here my code for CakePHP 3.7.9:

pdf.ctp

<?php
    header('Content-Type: application/pdf');
    require_once(ROOT . DS . 'vendor' . DS . 'fpdf182' . DS . 'fpdf.php');

    $pdf = new FPDF();
    $pdf->AddPage();
    $pdf->SetFont('Arial','B',16);
    $pdf->Cell(40,10,'Hello World!');
    $pdf->Output();

the related controller's function is empty. I'm going to put there the variables to print. Browsing to the test pdf page I get the un-decoded data:

%PDF-1.3 3 0 obj <> endobj 4 0 obj <> stream x�3R��2�35W(�r Q�w3T04�30PISp �Z*�[����(hx����+���(j*�d��7W endstream endobj 1 0 obj <> endobj 5 0 obj <> stream x�]R�n�0��>��L�%�DI�8���~�%Er�ﻻvҪHX�gvVk?/���Ῑ��`]�[�x5 �3\z��P�}����PO���j�Jݍ^���x6/f�����������|���4}�z�����}���@�,ۖ-��˺E�u�^�,���<� �Z_�K� IQ����Yd����C�K�_�%q�8>�!J"V!2&bGģ%r"H��D��}2EL1n��h�j���e��"aH����:��d��9c���[�X1~��"�3�g��Ñ�;O��> endobj 2 0 obj << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] /Font << /F1 6 0 R >> /XObject << >> >> endobj 7 0 obj << /Producer (FPDF 1.82) /CreationDate (D:20191229180430) >> endobj 8 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 9 0000000000 65535 f 0000000228 00000 n 0000000867 00000 n 0000000009 00000 n 0000000087 00000 n 0000000315 00000 n 0000000749 00000 n 0000000971 00000 n 0000001047 00000 n trailer << /Size 9 /Root 8 0 R /Info 7 0 R >> startxref 1096 %%EOF

It seems clear to me that the browser is reading the content literally instead of decoding it as pdf. Isn't the application/pdf header enough? Which other headers I need?

As said because I don't want to download the file by default, I'm not setting a filename.

1

1 Answers

2
votes

Do not user header() directly when using CakePHP, also don't try to send data to the browser manually, that's just going to cause problems, always use the abstract interfaces that the CakePHP response object provides!

If you want to set headers in the view layer, use $this->response, it's returned to the controller after rendering. However I would kinda be inclined to argue that a view template usually isn't really supposed to make such decisions, the view itself, that's more reasonable, and most of the time the controller layer will be the proper place.

Anyways, it works the same on controller, view and view template level, so here's an example:

$this->response = $this->response->withType('pdf');
$this->response = $this->response->withHeader(
    'Content-Disposition', 'inline; filename="some.pdf"'
);

Note that you can't use withDownload() as that will use attachment instead of inline.

Also if you use a view template, you should just echo the PDF contents then, ie use the FPDF::Output() method's $dest argument accordingly:

echo $pdf->Output('S'); // S = return String

See also