7

I am trying to build a CSV file in PHP, then call the PHP file from an AJAX call, which will then initiate a download of the CSV file upon success of the AJAX call. This works fine if I save a physical copy of the .csv on the server, but I would like to use php://ouput so I do not have to worry about physical files clogging up the server. Is it possible to initiate a download from returning php://output to AJAX? Here is my code:

HTML/jquery:

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" language="javascript" src="jquery.js"></script>
        <script type="text/javascript">
             $("#download").live("click", function() {
                var request = $.ajax({
                    dataType: 'html',
                    url: 'php.php',
                    success: function(response) {
                        alert('Finished');
                    }
                })
            })
        </script>
    </head>
    <body>
        <h1 id="download">DOWNLOAD</h1>
    </body>
</html>

PHP:

<?php 
    header('Content-type: application/vnd.ms-excel');
    header('Content-disposition: attachment; filename="test.csv"');
    $f = fopen('php://output', 'w');
    fwrite($f,'this,is,a,test');
    fclose($f);
    readfile('php://output');
    return;
?>

I am not sure how to get this to return a File Save dialog from my AJAX call.

This has to be simple, but I can't seem to find any examples that combines these two issues.

9
  • 1
    ajax isn't for file downloads. simply set the new iframe's src to be the download url and let it loose. Commented Oct 23, 2012 at 21:03
  • I would just open the page in a new window using window.open() since there isn't any output it should just initiate the download. Commented Oct 23, 2012 at 21:06
  • You seem to be a little confused as to what a URL is. A URL is an address of a resource on the internet. The URL could point to a file, or a PHP script, or any of a number of different things. Additionally, you're sending the wrong content-type. It should be text/csv Commented Oct 23, 2012 at 21:06
  • No need to open a new page if you have a hidden iframe that points to the php download address (as Marc wrote). Commented Oct 23, 2012 at 21:07
  • Not sure you are able to open save dialog from JavaScript ... should be potected! Commented Oct 23, 2012 at 21:09

4 Answers 4

3

You can do this by creating and sending form via jquery (page not reloaded):

$(document).on('click', '#download', function () {
    var form = $(document.createElement('form'));
    form.attr('action', 'php.php');
    form.attr('method', 'GET');
    form.appendTo(document.body);
    form.submit();
    form.remove();
});

Also you can pass post parameters if need:

$(document).on('click', '#download', function () {
    var form = $(document.createElement('form'));
    form.attr('action', 'php.php');
    form.attr('method', 'POST');
    var input = $('<input>').attr('type', 'hidden').attr('name', 'x').val('x value');
    form.append(input);
    form.appendTo(document.body);
    form.submit();
    form.remove();
});
Sign up to request clarification or add additional context in comments.

Comments

1

The following works, but is highly inneficient as it calls the php.php file twice. Does anybody have any better ideas?

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" language="javascript" src="jquery.js"></script>
        <script type="text/javascript">
             $("#download").live("click", function() {
                var request = $.ajax({
                    dataType: 'html',
                    url: 'php.php',
                    success: function(response) {
                        window.open('php.php');
                    }
                })
            })
        </script>
    </head>
    <body>
        <h1 id="download">DOWNLOAD</h1>
    </body>
</html>

Is there anyway to cache 'php.php' for just this instance so that it loads instantly under window.open('php.php'), but will reload contents when I click download next?

Why does window.open(response) not work the same?

Comments

1

look this:

if (!headers_sent()) {
    // seconds, minutes, hours, days
    $expires = 60*60*24*14;
    header('Pragma: public');
    header('Cache-Control: maxage=' . $expires);
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
}

Note: this will not work with POST requests, just GET.

Comments

-2

To allow for a file download, you can simply call the below code (say on a button's onclick):

window.open(<file-url>);

Hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.