PHP下载脚本通过AJAX调用不起作用

3

我在服务器上有一个简单的PHP脚本,目的是要下载指定的文件。如果我直接使用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);   
?>

但我希望从JavaScript启动这个脚本。因此,我尝试使用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();
}

虽然AJAX连接似乎成功了,但下载对话框没有被激活。我做错了什么?或者有另一个更简单的解决方案来启动下载吗?
1个回答

0

你误解了XMLHttpRequest的用途,它主要用于实现响应式功能,例如当我们想要加载由PHP生成的列表而不必重新加载页面时,

你可以使用它来实现,但是由于你不需要它, 一个简单的方法是打开一个_blank窗口到你提供的链接,这样你的函数将会是这样的:

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

并且在下载对话框出现后,窗口关闭了,所以你的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);   

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

?>

如果这对你不起作用,尽管窗口只会显示1秒钟左右,然后关闭,你可以使用。
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();
}

你需要模拟用户点击了一个带有该对象的元素。


谢谢,Zack。这正是我所需要的。而且比 AJAX 简单得多。 - reichi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接