0

Say I have the following pages:

index.php

<html>
   <form action="/make_file" method="get">
    <select name="client" style="width: 80%;">
     <?php foreach($clients as $client): ?> 
       <option value="<?=$client;?>"><?=$client;?></option>
     <?php endforeach; ?>
    </select>
    <input type="submit" value="Download Client Info">
   </form>
</html>

make_file.php

<?php
     $client = $_GET['client'];
     //check that client is valid and grab client information from the database

     $tmpfname = tempnam(sys_get_temp_dir(), $clientName);
     $handle = fopen($tmpfname, "w");

     //create a txt file containing information about the client

     header('Content-Description: File Transfer');
     header('Content-Type: application/octet-stream');
     header('Content-Disposition: attachment; filename="'.basename($tmpfname).'.txt"');
     header('Expires: 0');
     header('Cache-Control: must-revalidate');
     header('Pragma: public');
     header('Content-Length: ' . filesize($tmpfname));
     readfile($tmpfname);
     unlink($tmpfname);

     !!! //now here is where I'd like to create a custom message

?>

So in simple terms, I would like a user to be able to choose a client on index.php, then the make_file.php page will create and serve a text file with information about the client. But ideally, after that I would like to send a crafted alert message (via jquery/ajax..) to the user on index.php. The alert message will depend on the client and their information so it cannot be static.

I have tried several methods, but I'm having a problem with the fact that once you set the content-disposition header the whole output is put into the file (which is the expected behaviour) so I don't really know how to send this alert?

Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
user2827048
  • 539
  • 6
  • 18
  • 1
    Possible duplicate of [How do I execute some javascript after a file is downloaded?](http://stackoverflow.com/questions/14954121/how-do-i-execute-some-javascript-after-a-file-is-downloaded) or [Detect when browser receives file download](http://stackoverflow.com/questions/1106377/detect-when-browser-receives-file-download) – Sᴀᴍ Onᴇᴌᴀ Jan 19 '17 at 18:26
  • To the best of my knowledge, you cannot put the alert message code in the response from `make_file.php`. The only way I could see it working without a separate request would be setting the message as a cookie that the Javascript/jQuery would then parse as the message for the alert. – Spencer D Jan 19 '17 at 18:27

1 Answers1

0

Adapting the suggesion in this answer, we can set a cookie using setrawcookie() and rawurlencode() 1 right before calling readfile().

$message = 'hey there you picked client: '.$client.' tmpfilename: '.$tmpfname;
setrawcookie('message', rawurlencode($message), 2147483647, "/");

Then in the client-side page (i.e. index.php) we can add JavaScript (could utilize jQuery functions if you really wanted to but the code below is vanilla JS). It uses Event Delegation to add an event listener (with document.forms[0].addEventListener()) to the submission event on the form, setInterval() to create a function that runs periodically.

In that interval function, it checks for a cookie being set utilizing document.cookie. If a message is found in the cookies, then it decodes the message with decodeURIComponent(), sends that message to the alert() and clears the interval using clearInterval().

<!-- form HTML-->
</form>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',function(DOMReadyEvent) {
  document.forms[0].addEventListener('submit',startMessageCheck);
});
var messageCheck;
function startMessageCheck(formSubmitEvent) {
  messageCheck = window.setInterval(function() {
    var message = getCookie('message');
    if (message) {
      var decodedMessage = decodeURIComponent(message);
      alert('message: '+decodedMessage);
      deleteCookie('message');
      window.clearInterval(messageCheck);
    }
  },1000);
}
function getCookie( name ) {
  var parts = document.cookie.split(name + "=");
  if (parts.length == 2) {
          return parts.pop().split(";").shift();
  }
}
function deleteCookie( cName ) {
  document.cookie = cName + "=; Path=/; Expires=" + new Date( 0 ).toUTCString();
}
</script>

A demonstration of this can be seen on this page.


1 Initially I used setcookie() but was having issues with the default string encoding in the client-side.

Community
  • 1
  • 1
Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58