0

I want to fire a download window from an Ajax query.

The Ajax query is launched when I click on a button on my page.

Here is the Ajax query (function called on click on the button):

function exportDetailOuvrage(idData){

    $.ajax({
        url : 'ouvrage.php',
        type : 'POST',
        data : { typeOuvrage : idData },
        success : function (data){
            $('body').append(data);
        }
    });
}

Here is the PHP code to generate the CSV:

<?php

$csv = "Town;Name;Code\r\n" ;

foreach($result as $row){

    $csv .= $row['town'].";".$row['name'].";".$row['code']."\r\n" ;

}

header("Content-Type: text/csv; charset=utf-8");
header("Content-Disposition: attachment; filename=data.csv");

echo $csv;

?>

In the PHP code, $result is an array built on a SQL query in a database.

The CSV string is generated as wanted, the server answer is 200 (no errors using firebug). I have checked the sent parameters and the CSV string returned: everyting is OK.

The only issue is that no download window appears and no data.csv file is saved...

I was wondering if my Ajax code, especially the content of success parameter is good. I don't know what to put exactly inside this parameter.


EDIT :

According to @MonkeyZeus answer and comments, here is the content of my gimme_file.php:

<?php

    session_start();

    header("Content-Type: text/csv; charset=utf-8");
    header("Content-Disposition: attachment; filename=data.csv");
    readfile($_SESSION['I_CAN_DOWNLOAD_ONLY_THIS']);

    exit;

?>

I get the following error message inside the data.csv downloaded file:

<br />
<b>Notice</b>:  Undefined index: I_CAN_DOWNLOAD_ONLY_THIS in <b>D:\STAT\modele\gimme_file.php</b> on line <b>7</b><br />
<br />
<b>Warning</b>:  readfile(): Filename cannot be empty in <b>D:\STAT\modele\gimme_file.php</b> on line <b>7</b><br />
wiltomap
  • 3,933
  • 8
  • 37
  • 54
  • Look in your browser's console. Are you seeing a proper request / response? – Jay Blanchard Feb 16 '16 at 15:00
  • Yes indeed! Request and response are perfectly filled. The issue really seems to be about firing the download window... – wiltomap Feb 16 '16 at 15:02
  • 2
    Possible duplicate of [Download CSV file using "AJAX"](http://stackoverflow.com/questions/3346072/download-csv-file-using-ajax) and [this](http://stackoverflow.com/questions/6668776/download-file-through-an-ajax-call-php) and [this](http://stackoverflow.com/questions/33396580/ajax-and-downloading-csv-file) and [this](http://stackoverflow.com/questions/23051215/ajax-call-to-download-a-csv-file). You get the idea. Do some basic searching first. – Patrick Q Feb 16 '16 at 15:04

1 Answers1

3

Javascript (jQuery) can absolutely NOT trigger a file download natively; it would be a gigantic security issue.

What you must do is the following:

  1. Call the CSV generator
  2. Save the CSV to the server with a unique name
  3. Pass this unique name to your success: callback
  4. Use window.location to redirect the browser to the CSV file

My apologies if my post is very terse but I just do not want you to chase your tail for hours trying to achieve something that is fundamentally blocked by web browsers.


jQuery

function exportDetailOuvrage(idData){

    $.ajax({
        url : 'ouvrage.php',
        type : 'POST',
        data : { typeOuvrage : idData },
        success : function (data){
            window.location = 'http://www.mywebsite.com/gimme_file.php';
        }
    });
}

ouvrage.php

<?php

session_start();

$csv = "Town;Name;Code\r\n" ;

foreach($result as $row){

    $csv .= $row['town'].";".$row['name'].";".$row['code']."\r\n" ;

}

$filename = 'ouvrage_'.uniqid('', TRUE).'.csv';

file_put_contents($filename, $csv);

$_SESSION['I_CAN_DOWNLOAD_ONLY_THIS'] = $filename;

?>

gimme_file.php

<?php
session_start();

header("Content-Type: text/csv; charset=utf-8");
header("Content-Disposition: attachment; filename=data.csv");
readfile($_SESSION['I_CAN_DOWNLOAD_ONLY_THIS']);
exit;

?>
MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
  • Thanks @MonkeyZeus! I tried your code and it seems to improve. I get the following error messages inside the downloaded CSV: (1) `Undefined variable: _SESSION in D:\STAT\modele\gimme_file.php` and (2) `readfile(): Filename cannot be empty in D:\STAT\modele\gimme_file.php`. What do you expect to put inside `$_SESSION`? – wiltomap Feb 16 '16 at 15:43
  • @wiltomap It sounds like you forgot `session_start();` like I showed in my examples. – MonkeyZeus Feb 16 '16 at 19:02
  • No, I did mention it in `gimme_file.php`! That's why the error messages seem strange... Any idea on the origin of this issue? I'm so close to it now. Thanks for your advice! – wiltomap Feb 16 '16 at 20:30
  • @wiltomap Please update your question and add the code from `gimme_file.php`. Also, please mention which line number the error message is pointing to. Also, according to the error that you commented I am going to guess that you are missing a dollar symbol in front of `_SESSION` – MonkeyZeus Feb 16 '16 at 20:44
  • @wiltomap interesting, so your `ouvrage.php` is the same as my example as well? – MonkeyZeus Feb 17 '16 at 13:17
  • I had forgotten the `session_start();` at the beginning of `ouvrage.php` file... It seems to work nicely at present! I have lots of PHP files for my website, would you advice me to put a `session_start();` at the top of each file? Or is it just necessary for the `$_SESSION` variable? – wiltomap Feb 17 '16 at 13:27
  • Correct, it is only necessary for the `$_SESSION` variable. If you ever want to build a site with user credentials and a login page then you will need to understand `session_start();` at a much deeper level. The solution I provided in my answer is basically a band-aid fix. – MonkeyZeus Feb 17 '16 at 14:41