Prompt user to save file through AJAX call

ad2387 picture ad2387 · Aug 23, 2012 · Viewed 9.1k times · Source

I'm exporting my DHTMLX grid to csv and have successfully been able to create the .CSV file. The problem I'm having is that it isn't prompting the user to save/open the file. I'm using a $.post call from javascript to send the CSV string to PHP, then writing that string to csv. For some reason it isn't creating a prompt for the user, but it is successfully writing the file and saving on the server. Below is the relevant code:

JS:

myGrid.csvParser = myGrid.csvExtParser;
myGrid.setCSVDelimiter('|');
myGrid.csv.row = "endOfRow";           
var gridCsvData = myGrid.serializeToCSV();

    $.post(
        "data/export.php", 
        { 
           csvdata: gridCsvData
        }
    );

PHP (export.php):

$csvData = $_REQUEST['csvdata'];

$csv = explode('endOfRow',$csvData);

$myfile = "grid.csv";

$fh = fopen($myfile, 'w') or die("can't open file");

foreach($csv as $line) {
    fputcsv($fh, explode('|',$line),',','"');
}

fclose($fh);

//Redirect output to a client's web browser (csv)
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=grid.csv");
header("Pragma: no-cache");
header("Expires: 0");

This code works perfectly in the sense that it exports the Grid exactly how I want it and saves it to 'grid.csv'. The problem is that it isn't prompting the user to save the file. Is this a problem with my PHP headers or do I need to put something in the $.post to prompt on success? Thanks for any help!

Answer

Rocket Hazmat picture Rocket Hazmat · Aug 23, 2012

You can't prompt the user to download a file from an AJAX call. One thing you can do is, make an iFrame, put a form in it, then POST it. That way, it'll look like an AJAX call, but the user will be prompted to download the file.

// Create iFrame
var iframe = document.createElement('iframe');
iframe.style.display = "none";
document.body.appendChild(iframe);

// Get the iframe's document
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;

// Make a form
var form = document.createElement('form');
form.action = 'data/export.php'; // Your URL
form.method = 'POST';

// Add form element, to post your value
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'csvdata';
input.value = gridCsvData;  // Your POST data

// Add input to form
form.appendChild(input);

// Add form to iFrame
// IE doesn't have the "body" property
(iframeDoc.body || iframeDoc).appendChild(form);

// Post the form :-)
form.submit();

P.S. Your PHP code doesn't actually echo the CSV to the screen, it just saves it to a file.

After the header calls, make sure you have:

readfile($myfile);