Dowload file with ajax and php

tweetysat

In my html, I have

$('#vcc').click(function() { get_file() } );

function get_file()
{
    $.ajax({ url: "test.php",context: document.body})
    .done(function(text)
    {
    ....
    });
}

In test.php I'm generating a pdf document.

    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header("Content-Type: application/force-download");
    header('Content-Disposition: attachment; filename=' . urlencode(basename("factures/facture_2015_03.pdf")));
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . strlen($response));

    ob_clean();
    flush();
    echo $response;

If I call directly test.php, it's working, the file is downloaded.

Now I'd like to have it working with an ajax call. But I don't know what to put in the ... I tried with a document.write. The content of the pdf file is shown in my browser but not downloaded.

What can I do ?


EDIT:

Now my local.php contains

<html>

<head>
    <script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
    <script type="text/javascript">

    $( document ).ready(function() { document_ready(); } );

    function document_ready()
    {
        $('#vcc').click(function() { get_ajax() } );

        $.ajaxTransport("+binary", function(options, originalOptions, jqXHR)
        {
            // check for conditions and support for blob / arraybuffer response type
            if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob)))))
            {
                return {
                        // create new XMLHttpRequest
                        send: function(_, callback){
                            // setup all variables
                            var xhr = new XMLHttpRequest(),
                                url = options.url,
                                type = options.type,
                                // blob or arraybuffer. Default is blob
                                dataType = options.responseType || "blob",
                                data = options.data || null;

                            xhr.addEventListener('load', function(){
                                var data = {};
                                data[options.dataType] = xhr.response;
                                // make callback and send data
                                callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
                            });

                            xhr.open(type, url, true);
                            xhr.responseType = dataType;
                            xhr.send(data);
                        },
                        abort: function(){
                            jqXHR.abort();
                        }
                    };
                }
            });
        }

        function get_ajax()
        {
            $.ajax({
                  url: "remote.php",
                  // data that you want send to PHP script
                  data: { fileId: "random", extraData: "some value" },
                  type: "GET", // or POST
                  dataType: "binary", // make our special transfer type
                  processData: false,
                  success: function(text)
                  {
                  var pdfContent = [text]; // change to Array
                  var fakeFile= new Blob(pdfContent, {type: 'application/pdf'});
                  SaveToDisk(fakeFile, "form1.pdf")
                  }
                });
        }

        function SaveToDisk(blobURL, fileName) {
            var reader = new FileReader();
            reader.readAsDataURL(blobURL);
            reader.onload = function (event) {
                var save = document.createElement('a');
                save.href = event.target.result;
                save.target = '_blank';
                save.download = fileName || 'unknown file';

                var event = document.createEvent('Event');
                event.initEvent('click', true, true);
                save.dispatchEvent(event);
                (window.URL || window.webkitURL).revokeObjectURL(save.href);
            };
        }

    </script>
</head>

<body>

<div>
    <input type="submit" id="vcc" value="Go"></input>
</div>

</body>

and remote.php

<?php 

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . urlencode(basename("form1.pdf")));
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');

$response = readfile("form1.pdf");

header('Content-Length:' . strlen($response));

ob_clean();
flush();

print  $response;

?>

And the result

enter image description here

JerzySkalski

I'm not sure [my other solution with jQuery does not work in Firefox..]. Like many others said, you should not use AJAX/jQuery to make web browser download file.

Example:

page.htm with download link/button/anything:

<!doctype html>
<html>
<head>
    <title>Download fake file from JS script example</title>
    <meta charset="utf-8">
    <script>
function downloadPdfExample()
{
    // simple :)
    window.location = "download_pdf.php";
}
    </script>
</head>
<body>
Click on button below to start download:<br />
<button onclick="downloadPdfExample()">Start PDF download</button><br />

</body>
</html>

download_pdf.php file that will force browser to download file, not show in new card/current card:

<?php
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . urlencode(basename("form1.pdf")));
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
readfile("example.pdf");

flush();

I thought too much about JS code and forgot about PHP.

As you can see in example on PHP page ( http://php.net/manual/en/function.readfile.php#example-2524 ) readfile('filename'); does not return file content. It prints it on 'output'!

So.. this part of code:

$response = readfile("form1.pdf");
header('Content-Length:' . strlen($response));

Throws error! You cannot set response header AFTER you send file content (readfile send file content to browser, not put it variable $response!)

In $response is LENGTH of data sent to browser, so strlen($reponse) also does not work.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related