直接下载但无法从Web应用程序调用的PHP可以下载zip文件

时间:2018-12-31 15:55:26

标签: javascript php ajax post download

我有一个PHP代码,该代码可生成一个zip文件,并使其可从浏览器下载。下载部分如下:

download.php

// force client download
if (headers_sent()) {
    echo 'HTTP header already sent';
} else {
    if (!is_file($zipFile)) {
    header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
    echo $zipFile . ' not found';
    } else if (!is_readable($zipFile)) {
        header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
        echo $zipFile . ' not readable';
    } else {
        ob_start();
        // http headers for zip downloads
        header('Content-Description: File Transfer');
        header('Content-Type: application/zip');
        header('Content-Disposition: attachment; filename="' . $zipName . '"');
        header('Content-Transfer-Encoding: binary');
        header('Connection: Keep-Alive');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');

        set_time_limit(0);
        ob_flush();
        ob_clean();
        readfile($zipFile);
    }
}

直接像localhost/download.php这样从浏览器中调用时,它的工作原理使我可以正确下载压缩文件。

但是,我需要从JS Web应用程序中调用它。

我调用它的方式是通过如下所示的POST AJAX请求:

var xhr;
if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); // all browsers
else xhr = new ActiveXObject("Microsoft.XMLHTTP"); // for IE

var php_url = '/localhost/download.php' // ?wfs_url=' + url + 'format=' + format_list[0];
// (https://stackoverflow.com/a/53982364/1979665)
var formData = new FormData();
formData.append('wfs_url', url);
formData.append('format', format_list[0]);
xhr.open('POST', php_url);
xhr.onreadystatechange = function () {
    if (xhr.readyState===4 && xhr.status===200) {
        alert('Server reply: ' + xhr.responseText);
    }
}
xhr.send(formData);

return false;

当我点击一个按钮时,代码被触发。

显然,它在做“某事”。 PHP中间输出(某些文件夹)已正确创建,但下载未开始。

alert('Server reply: ' + xhr.responseText);部分显示了一条带有一些凌乱符号的奇怪消息,我猜这是从创建的文件中获得的,并以某种方式将其读取为文本。

这是消息的屏幕截图:

enter image description here

2 个答案:

答案 0 :(得分:2)

PHP脚本正在发送zip文件的实际二进制源,而AJAX请求正尝试将其显示为文本,这就是您得到的垃圾

如果您真的想保留AJAX(将<form>发送到download.php会更简单),则可以做两件事:

答案 1 :(得分:0)

按照@Gabriel的选项2接受答案后,我能够使我的代码正常工作。这是JS的修改版本(我没有对PHP代码进行任何更改):

var php_url = '/localhost/download.php' // ?wfs_url=' + url + 'format=' + format_list[0];
// (https://stackoverflow.com/a/53982364/1979665)
var formData = new FormData();
formData.append('wfs_url', url);
formData.append('format', format_list[0]);
xhr.open('POST', php_url);
xhr.onreadystatechange = function () {
    if (xhr.readyState===4 && xhr.status===200) {
        var blob = new Blob([xhr.response], { // SOLUTION
            type: "application/zip", // SOLUTION
        }); // SOLUTION
        var filename = "test.zip"; // SOLUTION
        if (navigator.msSaveOrOpenBlob) { // SOLUTION
            navigator.msSaveOrOpenBlob(blob, filename); // SOLUTION
        } else { // SOLUTION
            var a = document.createElement("a"); // SOLUTION
            document.body.appendChild(a); // SOLUTION
            a.style = "display:none"; // SOLUTION
            var url = window.URL.createObjectURL(blob); // SOLUTION
            a.href = url; // SOLUTION
            a.download = filename; // SOLUTION
            a.click(); // SOLUTION
            window.URL.revokeObjectURL(url); // SOLUTION
            a.remove(); // SOLUTION
         } // SOLUTION
    }
}
xhr.responseType = "arraybuffer"; // SOLUTION
xhr.send(formData);