Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/88.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何将deflated/gzip内容与XHR onProgress函数一起使用?_Javascript_Jquery_Xmlhttprequest_Compression - Fatal编程技术网

Javascript 如何将deflated/gzip内容与XHR onProgress函数一起使用?

Javascript 如何将deflated/gzip内容与XHR onProgress函数一起使用?,javascript,jquery,xmlhttprequest,compression,Javascript,Jquery,Xmlhttprequest,Compression,我以前见过很多类似的问题被问到,但我还没有找到一个能准确描述我当前问题的问题,所以下面是: 我有一个页面,它通过AJAX加载一个大的(0.5到10 MB)JSON文档,以便客户端代码可以处理它。一旦文件被加载,我就不会有任何意想不到的问题。但是,下载需要很长时间,因此我尝试利用呈现进度条来向用户指示文档正在加载。这很有效 然后,为了加快速度,我尝试通过gzip和deflate在服务器端压缩输出。这也奏效了,获得了巨大的收益,然而,我的进度条停止了工作 我已经研究了这个问题一段时间,发现如果请求的

我以前见过很多类似的问题被问到,但我还没有找到一个能准确描述我当前问题的问题,所以下面是:

我有一个页面,它通过AJAX加载一个大的(0.5到10 MB)JSON文档,以便客户端代码可以处理它。一旦文件被加载,我就不会有任何意想不到的问题。但是,下载需要很长时间,因此我尝试利用呈现进度条来向用户指示文档正在加载。这很有效

然后,为了加快速度,我尝试通过gzip和deflate在服务器端压缩输出。这也奏效了,获得了巨大的收益,然而,我的进度条停止了工作

我已经研究了这个问题一段时间,发现如果请求的AJAX资源没有发送适当的
内容长度
头,那么
onProgress
事件处理程序就无法按预期运行,因为它不知道下载的时间有多长。发生这种情况时,事件对象上名为
lengthComputeable
的属性被设置为
false

这是有道理的,所以我尝试使用输出的未压缩和压缩长度显式设置头。我可以验证是否发送了标题,我可以验证我的浏览器是否知道如何解压缩内容。但是
onProgress
处理程序仍然报告
lengthComputeable=false

所以我的问题是:有没有办法用AJAX Progress API压缩/压缩内容?如果有,我现在做错了什么


这是资源在Chrome网络面板中的显示方式,显示压缩正在工作:

这些是相关的请求头,表明请求是AJAX,并且
接受编码
设置正确:

GET/dashboard/reports/ajax/load HTTP/1.1
连接:保持活力
缓存控制:没有缓存
Pragma:没有缓存
接受:application/json,text/javascript,*/*;q=0.01
X-request-With:XMLHttpRequest
用户代理:Mozilla/5.0(Macintosh;英特尔Mac OS X 10_7_5)AppleWebKit/537.22(KHTML,如Gecko)Chrome/25.0.1364.99 Safari/537.22
接受编码:gzip、deflate、sdch
接受语言:en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3
这些是相关的响应标题,表明
内容长度
内容类型
设置正确:

HTTP/1.1200正常
缓存控制:无存储,无缓存,必须重新验证,后检查=0,预检查=0
内容编码:deflate
内容类型:application/json
日期:2013年2月26日星期二18:59:07 GMT
到期时间:1981年11月19日星期四格林威治标准时间08:52:00
P3P:CP=“我们的”
Pragma:没有缓存
服务器:Apache/2.2.8(Unix)mod_ssl/2.2.8 OpenSSL/0.9.8g PHP/5.4.7
X-Powered-By:PHP/5.4.7
内容长度:223879
连接:保持活力
值得一提的是,我已经在标准(http)和安全(https)连接上尝试了这一点,没有任何区别:内容在浏览器中加载良好,但没有被Progress API处理


根据,我尝试将服务器端切换到gzip编码,但没有成功或更改。以下是相关的响应标题:

HTTP/1.1200正常
缓存控制:无存储,无缓存,必须重新验证,后检查=0,预检查=0
内容编码:gzip
内容类型:application/json
日期:2013年3月4日星期一格林尼治标准时间22:33:19
到期时间:1981年11月19日星期四格林威治标准时间08:52:00
P3P:CP=“我们的”
Pragma:没有缓存
服务器:Apache/2.2.8(Unix)mod_ssl/2.2.8 OpenSSL/0.9.8g PHP/5.4.7
X-Powered-By:PHP/5.4.7
内容长度:28250
连接:保持活力
重复一次:内容正在被正确下载和解码,这只是我遇到麻烦的ProgressAPI


佩尔,以下是请求:

$.ajax({
    url: '<url snipped>',
    data: {},
    success: onDone,
    dataType: 'json',
    cache: true,
    progress: onProgress || function(){}
});

尝试将服务器编码更改为gzip。

您的请求头显示了三种可能的编码(gzip、deflate、sdch),因此服务器可以选择这三种编码中的任何一种。通过响应头,我们可以看到您的服务器选择使用deflate进行响应

Gzip是一种编码格式,除了额外的页眉和页脚(包括原始未压缩长度)和不同的校验和算法外,还包括一个deflate有效负载:

Deflate有一些问题。由于处理不正确解码算法的遗留问题,deflate的客户端实现必须进行愚蠢的检查,以确定它们处理的是哪一个实现,不幸的是,它们仍然经常出错:

在你的问题中,浏览器可能会看到一个泄气文件从管道中流下来,然后举起手臂说,“当我甚至不知道如何解码这个东西时,你怎么能指望我担心进度是否正确,人类?”


如果您切换服务器配置,使响应是gzip(即gzip显示为内容编码),我希望您的脚本能够像您希望/预期的那样工作。

不要因为没有本机解决方案而陷入困境;一行黑客可以在不影响Apache配置的情况下解决您的问题(在某些主机中是禁止的或非常受限的):

PHP拯救:

var size = <?php echo filesize('file.json') ?>;
var size=;
就这样,您可能已经知道了其余内容,但作为参考:

<script>
var progressBar = document.getElementById("p"),
    client = new XMLHttpRequest(),
    size = <?php echo filesize('file.json') ?>;

progressBar.max = size;

client.open("GET", "file.json")

function loadHandler () {
  var loaded = client.responseText.length;
  progressBar.value = loaded;
}

client.onprogress = loadHandler;

client.onloadend = function(pe) {
  loadHandler();
  console.log("Success, loaded: " + client.responseText.length + " of " + size)
}
client.send()
</script>

var progressBar=document.getElementById(“p”),
client=new XMLHttpRequest(),
大小=;
progressBar.max=大小;
client.open(“GET”、“file.json”)
函数loadHandler(){
加载的变量=client.responseText.length;
progressBar.value=已加载;
}
client.onprogress=loadHandler;
client.onloadend=函数(pe){
loadHandler();
log(“成功,加载:“+client.responseText.length+”,大小为“+size”)
}
client.send()
现场示例:<
<script>
var progressBar = document.getElementById("p"),
    client = new XMLHttpRequest(),
    size = <?php echo filesize('file.json') ?>;

progressBar.max = size;

client.open("GET", "file.json")

function loadHandler () {
  var loaded = client.responseText.length;
  progressBar.value = loaded;
}

client.onprogress = loadHandler;

client.onloadend = function(pe) {
  loadHandler();
  console.log("Success, loaded: " + client.responseText.length + " of " + size)
}
client.send()
</script>
function loader(onDone, onProgress, url, data)
{
    // onDone = event handler to run on successful download
    // onProgress = event handler to run during a download
    // url = url to load
    // data = extra parameters to be sent with the AJAX request
    var content_length = null;

    self.meta_xhr = $.ajax({
        url: url,
        data: data,
        dataType: 'json',
        type: 'HEAD',
        success: function(data, status, jqXHR)
        {
            content_length = jqXHR.getResponseHeader("X-Content-Length");
        }
    });

    self.xhr = $.ajax({
        url: url,
        data: data,
        success: onDone,
        dataType: 'json',
        progress: function(jqXHR, evt)
        {
            var pct = 0;
            if (evt.lengthComputable)
            {
                pct = 100 * evt.position / evt.total;
            }
            else if (self.content_length != null)
            {
                pct = 100 * evt.position / self.content_length;
            }

            onProgress(pct);
        }
    });
}
loader(function(response)
{
    console.log("Content loaded! do stuff now.");
},
function(pct)
{
    console.log("The content is " + pct + "% loaded.");
},
'<url here>', {});
header("X-Content-Length: ".strlen($payload));
if ($_SERVER['REQUEST_METHOD'] == "HEAD")
{
    exit;
}
request.onProgress = function (e) {
  var contentLength;
  if (e.lengthComputable) {
    contentLength = e.total;
  } else {
    contentLength = parseInt(e.target.getResponseHeader('x-decompressed-content-length'), 10);
  }
  progressIndicator.update(e.loaded / contentLength);
};
<IfModule mod_deflate.c>
DeflateBufferSize 10000000
</IfModule>
<IfModule mod_headers.c>
    Header set Access-Control-Expose-Headers "Content-Length"
</IfModule>
var total = e.total;
if(!e.lengthComputable){
total = e.target.getResponseHeader('content-length') * 2.2;
} 
// Some times 100 reached in the progress event more than once.
if(preloadedResources < resourcesLength && progressPercentage < 100) {
    canIncreaseCounter = true;
}
if(progressPercentage >= 100 && canIncreaseCounter && preloadedResources < resourcesLength) {
    preloadedResources++;
    canIncreaseCounter = false;
}