0
votes

I'm submitting a form with ajax and after the form is submitted I need to download a pdf file generated on the server side with the php library mpdf. I don't want to save the pdf file in the server because after the user donwloads the file is not needed anymore. I've searched on google and someone suggest to use a Blob object. I'm also returning a json response to show to the user. Can someone explain if it is possible and how to achieve it? many thanks

this is my javascript code:

              $.ajax({

                    type: form.method,
                    data: $(form).serialize(),
                    dataType: 'JSON',

                    beforeSend: function() {
                        // Show loader
                        $(".loader").show();
                    },


                    success: function(response) {

                        // Hide loader
                        $(".loader").hide();


                        if (response.error_code == '200') {

                            // Add class alert danger to the message
                            $('.alert', $('.horizontal-form')).addClass('alert-success').show();
                            // Show error message
                            $('#error_message').html(response.error_message);
                            // Remove default validation error message from template
                            $('#error_message').get(0).nextSibling.remove();
                            // Remove class alert danger if was left by previous validation
                            $('.alert', $('.horizontal-form')).removeClass('alert-danger');
                            // reset form fields
                            form.reset();
                            // Scroll back to show success message
                            scrollTo(success, -200);

                        }

                    }

                });

and this is my php code

if(isset($_POST['userLetter'])){

                        header("Content-Type", "application/pdf");

                        // Render the view using twig and pass params to it
                        $html=$twig->render('/km-letters/km-letter-new-user.twig', array(
                            // Render user details on twig topbar
                            'prova' => 'pippo'

                        ));

                        $mpdf->WriteHTML($html);


                        return $mpdf->Output('foobar-' . time() . '.pdf','D');


                    }

Also from the response i get the following header and i can see the pdf file:

Cache-Control
public, must-revalidate, max-age=0 Connection
Keep-Alive Content-Description File Transfer Content-Disposition attachment; filename="doc.pdf" Content-Transfer-Encoding
binary Content-Type
application/pdf Date
Sun, 10 Mar 2019 11:11:35 GMT Expires Sat, 26 Jul 1997 05:00:00 GMT Keep-Alive
timeout=5, max=99 Last-Modified
Sun, 10 Mar 2019 11:11:35 GMT Pragma
public Server
Apache Transfer-Encoding
chunked X-Generator mPDF 7.1.9 X-Powered-By
PHP/7.3.0

But i also get the following very long string response:

XHRPOSThttp://router.kondomatica.me/km-users/createUser#[HTTP/1.1 200 OK 332ms] HeaderCookieParametriRispostaTempiAnalisi dello stackPayload rispostax1JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL01lZGlhQm94IFswIDAgNTk1LjI4MCA4NDEuODkwXQo

1
Create the file temporarily and after returning it to the user, you could use unlink() to remove it.pmatsumura
Hi @pmatsumura thanks for your reply, do I need to unlink() the file after this has been downloaded? How do i detect if ita has been downloaded?pippo
You shouldn't need to worry about deleting files, since you are telling mPDF to output the file as download. The generated PDF will be saved in RAM and will be removed from RAM after it has been sent to the browser.pmatsumura
Ok @pmatsumura but how can i achieve this? The code I've posted doesn't seem to work.pippo
It's not possible to download a file wih Ajax. See this post for more info on this: stackoverflow.com/questions/4545311/…pmatsumura

1 Answers

1
votes

Based on the comments from the question, here is an untested solution, that should work.

Since javascript can't save files due to security reasons, the code first creates a Blob object from the response and then an anchor pointing to the object URL of the Blob. Afterwards the anchor is added to the DOM, then "clicked" and then removed from the DOM.

$.ajax({
    type: form.method,
    data: $(form).serialize(),
    cache: false,

    beforeSend: function() {
        // Show loader
        $(".loader").show();
    },

    success: function(response, responseCode, xhr) {
        // Hide loader
        $(".loader").hide();

        if (responseCode == "200") {
            var disposition = xhr.getResponseHeader('content-disposition');
            var matches = /"([^"]*)"/.exec(disposition);
            var filename = (matches != null && matches[1] ? matches[1] : 'doc.pdf');
            var blob = new Blob(response, {
                type: 'application/pdf'
            });
            var link = document.createElement('a');

            link.href = window.URL.createObjectURL(blob);
            link.download = filename;

            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);

            // Add class alert danger to the message
            $(".alert", $(".horizontal-form"))
            .addClass("alert-success")
            .show();
            // Show error message
            $("#error_message").html(response.error_message);
            // Remove default validation error message from template
            $("#error_message")
            .get(0)
            .nextSibling.remove();
            // Remove class alert danger if was left by previous validation
            $(".alert", $(".horizontal-form")).removeClass("alert-danger");
            // reset form fields
            form.reset();
            // Scroll back to show success message
            scrollTo(success, -200);
        }
    }
});