【问题标题】:XMLHttpRequest readyState HEADERS_RECEIVED waiting for entire file to downloadXMLHttpRequest readyState HEADERS_RECEIVED 等待整个文件下载
【发布时间】:2014-12-28 09:58:53
【问题描述】:

According to MDNXMLHttpRequest readyState 事件触发 5 个事件,如下所列。

0    UNSENT              open()has not been called yet.
1    OPENED              send()has not been called yet.
2    HEADERS_RECEIVED    send() has been called, and headers and status are available.
3    LOADING             Downloading; responseText holds partial data.
4    DONE                The operation is complete.

这似乎表明HEADERS_RECEIVED 在整个文件下载之前可用,尤其是在长时间传输期间。但是,在我的测试中,虽然事件确实按此顺序触发,但 HEADERS_RECEIVEDLOADINGDONE 事件几乎同时触发。

这是一个说明我的问题的基本示例。 OPENED 事件会立即触发,但 HEADERS_RECEIVEDLOADINGDONE 都会等待 5 秒。我在 Firefox 和 Chrome 的本地 Apache 2.4 服务器上使用 PHP 5.5 运行了这个测试。

JavaScript:

var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
    console.log("readyState:", xmlhttp.readyState);
};
xmlhttp.open("GET", "handler.php", true);
xmlhttp.send();

handler.php:

<?php
header( 'Content-Type: text/plain' );
echo "start\n";
sleep( 5 );
echo "end\n";

似乎在内容之前获取标头的唯一方法是首先发出HEAD 请求,然后发出完整请求。这是预期的行为还是我遗漏了什么?

更新:

使用通过慢速网络共享符号链接的 1GB 文件,或输出大量输出的 PHP 文件(下面的示例)确实会更快地触发 HEADERS_RECEIVED。不过,这似乎有些不可靠。我在sleep 之前尝试过使用PHP 的flush 函数,但它没有帮助。

<?php
header( 'Content-Type: text/plain' );
echo "start\n";
$i = 10000000;
while( $i-- ){
    echo "1\n";
}
echo "end\n";

有没有办法在不等待内容发送的情况下可靠地发送标头?

【问题讨论】:

    标签: javascript php ajax apache xmlhttprequest


    【解决方案1】:

    至少在您的示例中,我猜 PHP 直到睡眠之后才真正刷新缓冲区(并因此发送标头),但我不确定如果您这样做是否可以解释这种行为使用实际文件下载遇到过它。

    【讨论】:

    • 我相信 PHP 中的输出缓冲区只用ob_flush() 刷新,我不相信flush() 会这样做。尝试使用ob_flush()
    • 有趣。我的理解是 ob_flush 只有在您以编程方式使用 ob_start 时才需要,但事实证明 PHP 可能(总是?)自动创建一定级别的输出缓冲。看来您可以通过调用ob_get_level 并检查它是否为非零来检测到这一点。 ob_flush 本身是不够的。看来您必须先调用ob_flush然后 flush,以首先刷新内部缓冲区,然后将其发送到客户端。这使事情变得更加复杂,但感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2012-02-29
    • 1970-01-01
    相关资源
    最近更新 更多