0

I have a simple web page where I make a database query through html button triggering ajax within javascript which is calling a php script to make the query into database. Then, fill all the result returned from the query into a csv file and download it.

The problem is when I check the wireshark capture, I can see the packet containing all the information I need within HTTP 200 OK packet. However, there is no download prompt for me to download the file.

Here are the headers in the packet:

HTTP/1.1 200 OK
Date: Thu, 06 Jul 2017 00:52:35 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux) PHP/5.4.16
X-Powered-By: PHP/5.4.16
Content-Description: File Transfer
Content-Disposition: attachment; filename=data.csv
Content-Length: 2968
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: application/csv; charset=utf-8

Media type: application/csv; charset=utf-8 (2968 bytes)

Let me know if any further information is needed.

EDIT #1 - added AJAX Code:

        $.ajax({
            url:"export_csv.php", //the page containing php script
            data: { userID : "L2Export", 'avc' : avc, 'connType' : connType },
            type: "POST", //request type
            success:function(result){
                console.log("ajax success");
            }

EDIT #2 - added PHP code:

$queryStatement = "SELECT * FROM ".$db_record." ".$where;
header("Content-Description: File Transfer");
header('Content-Type: application/csv; charset=utf-8'); 
header("Content-Disposition: attachment; filename=data.csv");
$output = fopen("php://output", "w");
fputcsv($output, array(<HEADERS ARE HERE>));  
$result = mysqli_query($conn, $queryStatement); 
//error_log("Here is the statement $queryStatement", 0);
while($row = mysqli_fetch_assoc($result))  {
    fputcsv($output, $row);
}
fclose($output);
mysqli_close($conn);
takobaba
  • 306
  • 1
  • 4
  • 15
  • 1
    HTML / JavaScript used... and FYI, there is a thing called Developer Tools on pretty much any standard browser, wireshark is a bit overkill. – Patrick Roberts Jul 06 '17 at 01:02
  • 1
    Show your code, a simple snippet of a http header isn't enough information – Patrick Evans Jul 06 '17 at 01:02
  • 1
    How do you trigger the latter php script? – Diligent Key Presser Jul 06 '17 at 01:02
  • 5
    FYI, doing an AJAX request doesn't trigger a download. The response is placed in the XHR [response](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response), [responseText](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText), or [responseXML](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML) (where appropriate) properties of the XHR instance that made the request. Additionally since you are using jQuery, the data is in the `result` argument of the `success` callback – Patrick Evans Jul 06 '17 at 01:04
  • I dont know if i can see incoming packets in developer tools thanks. shared the ajax part of the code. So, should I try to put that result into a file in AJAX and download rather than doing it in php? Sorry I am not an expert. Also, let me share the php snippet. – takobaba Jul 06 '17 at 01:06
  • You can see every part of a request in developer tools network tab – charlietfl Jul 06 '17 at 01:10
  • Possible duplicate of [Handle file download from ajax post](https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post) – Patrick Evans Jul 06 '17 at 01:10

1 Answers1

1

Creating an AJAX request does indeed fetch a resource from the server, but that response will not trigger a browser download prompt. To prompt a download on a POST request, you must submit a <form> and set the Content-Disposition header properly (which you have correctly done in PHP):

HTML:

<form method="POST" action="export_csv.php">
  <input type="hidden" name="userID" value="L2Export"/>
  <!-- other POST data... -->
  <button type="submit">Download CSV File</button>
</form>

You can even use JavaScript to dynamically add other hidden <input> fields if necessary in an event listener:

JavaScript:

var form = document.querySelector('form[action="export_csv.php"]');

form.addEventListener('submit', function (event) {
  var avcEl = form.querySelector('[name="avc"]') || document.createElement('input');
  var connTypeEl = form.querySelector('[name="connType"]') || document.createElement('input');

  avcEl.type = 'hidden';
  avcEl.name = 'avc';
  avcEl.value = avc; // get this how you did for the $.ajax()

  connTypeEl.type = 'hidden';
  connTypeEl.name = 'connType';
  connTypeEl.value = connType; // get this how you did for the $.ajax()

  // don't worry, these won't error if they're already children of <form>
  form.appendChild(avcEl);
  form.appendChild(connTypeEl);
});
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153