If you prefer to keep the logic entirely within the client-side after receiving data, you can use JavaScript to create a "virtual" link and click it programmatically.
: If generating files on the fly, use the temporary:// stream wrapper and implement a cron job to clean up old files. drupal ajax download file
: Return the file content (often Base64 encoded) inside a standard AjaxResponse . If you prefer to keep the logic entirely
: Since file generation can take time, use InvokeCommand to show a "Processing..." spinner when the AJAX starts and hide it once the download triggers. drupal ajax download file