从AJAX调用中下载使用PHP输出缓冲区构建的文件

7
我将尝试使用PHP构建CSV文件,然后从AJAX调用中调用PHP文件,在AJAX调用成功后启动CSV文件的下载。如果我在服务器上保存.csv的物理副本,则可以正常工作,但我想使用php://output,这样就不必担心物理文件堵塞服务器了。是否可能通过返回php://output来启动从AJAX的下载?以下是我的代码:
HTML / jquery:
<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" language="javascript" src="jquery.js"></script>
        <script type="text/javascript">
             $("#download").live("click", function() {
                var request = $.ajax({
                    dataType: 'html',
                    url: 'php.php',
                    success: function(response) {
                        alert('Finished');
                    }
                })
            })
        </script>
    </head>
    <body>
        <h1 id="download">DOWNLOAD</h1>
    </body>
</html>

PHP:

<?php 
    header('Content-type: application/vnd.ms-excel');
    header('Content-disposition: attachment; filename="test.csv"');
    $f = fopen('php://output', 'w');
    fwrite($f,'this,is,a,test');
    fclose($f);
    readfile('php://output');
    return;
?>

我不确定如何从我的AJAX调用中返回文件保存对话框。

这应该很简单,但我似乎找不到结合这两个问题的任何示例。


1
Ajax不适用于文件下载。只需将新iframe的src设置为下载URL,然后让它自由运行即可。 - Marc B
我会使用 window.open() 在新窗口中打开页面,因为没有任何输出,它应该只会启动下载。 - Pitchinnate
不确定您是否能够从 JavaScript 打开保存对话框... 应该要保护! - Reflective
有趣的方法将文件处理程序连接到输出流!我不知道这个。谢谢。 - Reflective
好的,我重新阐述一下我的问题。AJAX调用返回了正确的头部和主体,但它没有对它们进行任何操作。我该如何获取PHP的响应以打开保存文件对话框? - Das.Rot
显示剩余4条评论
4个回答

3
您可以通过使用jQuery创建并发送表单(页面不重新加载)来实现此操作:
$(document).on('click', '#download', function () {
    var form = $(document.createElement('form'));
    form.attr('action', 'php.php');
    form.attr('method', 'GET');
    form.appendTo(document.body);
    form.submit();
    form.remove();
});

此外,如果需要,您还可以传递POST参数:
$(document).on('click', '#download', function () {
    var form = $(document.createElement('form'));
    form.attr('action', 'php.php');
    form.attr('method', 'POST');
    var input = $('<input>').attr('type', 'hidden').attr('name', 'x').val('x value');
    form.append(input);
    form.appendTo(document.body);
    form.submit();
    form.remove();
});

1
以下代码可以正常工作,但是由于调用了两次php.php文件,效率非常低。有没有更好的想法?
<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" language="javascript" src="jquery.js"></script>
        <script type="text/javascript">
             $("#download").live("click", function() {
                var request = $.ajax({
                    dataType: 'html',
                    url: 'php.php',
                    success: function(response) {
                        window.open('php.php');
                    }
                })
            })
        </script>
    </head>
    <body>
        <h1 id="download">DOWNLOAD</h1>
    </body>
</html>

有没有一种方法可以仅针对此实例缓存 'php.php',以便在 window.open('php.php') 下立即加载,但在我点击 下载 后重新加载内容?

为什么 window.open(response) 不起作用?


1
看这个:
if (!headers_sent()) {
    // seconds, minutes, hours, days
    $expires = 60*60*24*14;
    header('Pragma: public');
    header('Cache-Control: maxage=' . $expires);
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
}

注意:这不适用于POST请求,只适用于GET请求。

-2
为了允许文件下载,您可以简单地调用下面的代码(例如在按钮的onclick事件中):
window.open(<file-url>);

希望这能有所帮助。

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