Downloading PDF from API via Javascript
Asked Answered
S

2

-1

i am using vue.js and found some good examples how to realize this.

Currently my API is returning a test-pdf:

    $snappy = App::make('snappy.pdf');

    $html = '<h1>Bill</h1><p>You owe me money, dude.</p>';

    return Response(
        $snappy->getOutputFromHtml($html),
        200,
        array(
            'Content-Type'          => 'application/pdf',
            'Content-Disposition'   => 'attachment; filename="file.pdf"'
        )
    );

Downloading the Content via Postman works well.

I managed the JS-part like this:

  export const InvoiceService = {
  get(slug) {
    return ApiService.get("invoice", slug);
  },
  downloadPdf(slug) {
    return ApiService.get(`pdf/invoice`, slug, {
      responseType: 'arraybuffer'
    });
  }
};

and:

InvoiceService.downloadPdf(invoiceId)
        .then(({ data }) => {
          let blob = new Blob([data], {
            type: "application/pdf"
          });
          FileSaver.saveAs(blob, "invoice.pdf");
        })
        .catch(error => {
          throw new Error(error);
        });

The download works fine but the file downloaded via js seems to be corruped (PDF wont show): enter image description here

The green marked text is the content of the working pdf.

I think something is messed up with the charset, but i ran out of Ideas :(

Hopefully someone can give me a hint - It drives me nuts :)

Best regards - Alex

Shatterproof answered 15/12, 2018 at 17:37 Comment(0)
S
0

transferring the pdf base64 encoded and converting the string into an blob finally worked:

PHP:

$pdf = App::make('snappy.pdf.wrapper');
$pdf->loadHTML('<h1>Test</h1>');
$pdf->setOption('encoding', 'UTF-8');
return base64_encode($pdf->output());

JS:

var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: "application/pdf" });

FileSaver.saveAs(blob, "invoice.pdf");
Shatterproof answered 18/12, 2018 at 17:14 Comment(0)
C
4

You can use Axios with responseType: 'blob'

// Function that downloads PDF
function download(data) {
  const url = URL.createObjectURL(data);
  const a = document.createElement('a');
  a.download = 'test.pdf';
  a.href = url;
  a.target = '_self';

  a.click();

  setTimeout(function () {
    // For Firefox it is necessary to delay revoking the ObjectURL
    a.remove();
    URL.revokeObjectURL(url);
  }, 100);
}

// Get data from the API
const response = await axios.get('URL', {
   responseType: 'blob', // THIS is very important, because we need Blob object in order to download PDF
});

// Invoke download function
download(response);

/////////////// Your response.data will look like this:response.data

Crash answered 23/2, 2022 at 16:57 Comment(1)
Thank you for the "very important" comment!!! myFileName.pdf (24).pdf has finally downloaded as expected.Gourley
S
0

transferring the pdf base64 encoded and converting the string into an blob finally worked:

PHP:

$pdf = App::make('snappy.pdf.wrapper');
$pdf->loadHTML('<h1>Test</h1>');
$pdf->setOption('encoding', 'UTF-8');
return base64_encode($pdf->output());

JS:

var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: "application/pdf" });

FileSaver.saveAs(blob, "invoice.pdf");
Shatterproof answered 18/12, 2018 at 17:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.