PHP download script does not work when called via AJAX


I have a simple PHP script on my the server, which should download a given file. It's working fine, if I invoke it directly with http://myDomain/download.php?filename=mini.gpx

download.php:

<?php
$dir = 'download/';
$file = $_GET['filename'];
$fqn = $dir . $file;
$fileSize = filesize($fqn);
header("Content-Type: text/xml");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Length: $fileSize");
readfile($fqn);   
?>

But I want to start this script out of JavaScript. So I tried to do it with an httpRequest:

function downloadGPXfile(fn) {
    let script = `downloadGPXfile.php?filename=${fn}`;
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        console.log("state downloadGPXfile: ", this.readyState);
        console.log("status: ", this.status);
    };
    xhr.open('GET', script, true);
    xhr.setRequestHeader('Content-Type', 'text/xml');
    xhr.send();
}

Although the AJAX connection seems to be successful, the download dialog is not activated. What do I wrong? Or is there another, simplier solution to start the download?

you missunderstand what XMLHttpRequest is for , it's used mainly for reactivity , for example when we want to load a list generated by php without having to reload the page ,

you can achive it with it , but since you don't need it a simple way would be to open a _blank window to the link you gave so your function will look like

function downloadGPXfile(fn) {
    let script = `downloadGPXfile.php?filename=${fn}`;
window.open('http://website/downloadGPXfile.php?filename=' + fn, '_blank');
}

and after the download dialog get showen the window is closed so your php will look like

<?php
$dir = 'download/';
$file = $_GET['filename'];
$fqn = $dir . $file;
$fileSize = filesize($fqn);
header("Content-Type: text/xml");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Length: $fileSize");
readfile($fqn);   

echo "
<script>
window.close();
</script>";

?>

if this doesn't work for you although just to be clear the window will be shown for like 1sec maximum and then closed you can use

function downloadGPXfile(fn) {
let fileurl = `http://website/downloadGPXfile.php?filename=${fn}`;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
    var downloadUrl = URL.createObjectURL(xhttp.response);
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    a.href = downloadUrl;
    a.download = "";
    a.click();
}
};
xhttp.open("GET", fileurl, true);
xhttp.responseType = "blob";
xhttp.send();
}

you see you need to stimulate like the user clicked an that has the object