HEAD 请求似乎是为了传输资源,而不仅仅是标头
看来我通过 jQuery 的 $.ajax({...});
方法发送的 HEAD
请求正在返回给定资源的内容(至少在 Firefox 中... IE 似乎运行正常),而不仅仅是标题。我试图仅捕获 Content-Length
标头属性,以在图像预加载器中使用,尽管似乎仅通过查询 Content-Length
就可以下载它内容本身。
这里的操作顺序是:
- 使用 CSS
background-image
查找给定页面中的所有元素,并使用 URL 填充数组 (imageTemp
)。 - 对于每个图像 URL,执行 Ajax
HEAD
请求,以获取Content-Length
并将其添加到bytesTotal
以及填充数组 (imageData
),同时包含 URL 和该图像的Content-Length
。- 同时启动
setInterval
事件处理程序以定期检查所有 AjaxHEAD
请求是否已完成。
- 同时启动
- 当
HEAD
请求完成后,开始将图像从imageData
加载到Image()
对象中,添加关联的图像Content-Length
值到bytesLoaded
值。\ - 当
bytesLoaded == bytesTotal
图像加载完成时,预加载器已完成。
这是我目前的脚本:
(function($){
var callbacks = {
initiate: function(){},
progress: function(percent){},
complete: function(){},
};
var imageTemp = Array();
var imageData = Array();
var imageCurrent = null;
var intervalId = 0;
var bytesLoaded = 0;
var bytesTotal = 0;
$.preloader = function(arguments){
for(var arg in arguments){
callbacks[arg] = arguments[arg];
}
callbacks.initiate();
$('*')
.each(function(index){
if($(this).css('background-image') != 'none'){
imageTemp.push($(this).css('background-image').slice(5, -2));
}
});
intervalId = window.setInterval(function(e){
if(imageData.length == imageTemp.length){
window.clearInterval(intervalId);
for(var i = 0; i < imageData.length; i++){
(function(imageIndex){
currentImage = new Image();
currentImage.src = imageData[imageIndex][0];
currentImage.onload = function(e){
bytesLoaded += parseInt(imageData[imageIndex][1]);
callbacks.progress(bytesLoaded/bytesTotal);
if(bytesLoaded >= bytesTotal){
callbacks.complete();
}
};
})(i);
}
}
}, 1);
for(var i = 0; i < imageTemp.length; i++){
(function(i){
$.ajax({
type: "HEAD",
async: true,
url: imageTemp[i],
success: function(message, text, response){
var bytes = parseInt(response.getResponseHeader('Content-Length'));
bytesTotal += bytes;
imageData.push([imageTemp[i], bytes]);
},
});
})(i);
}
};
})(jQuery);
这与我的问题直接相关 Ajax HEAD 请求通过 Javascript/jQuery,但它肯定不是重复的,因为该问题是从之前解决的问题扩展而来的。
It appears that the HEAD
requests I'm sending via jQuery's $.ajax({...});
method, are returning the content of the given resource (at least in Firefox... IE appears to function normally), rather than just headers. I'm trying to capture only the Content-Length
header property, for use in an image preloader, though it seems that by merely querying for the Content-Length
, it's downloaded the content itself.
The order of operation here, is:
- Find all elements in a given page with CSS
background-image
, and populate an array (imageTemp
) with the URLs. - For each image URL, perform an Ajax
HEAD
request, to obtain theContent-Length
and add that tobytesTotal
as well as populate the array (imageData
) with both the URL and that image'sContent-Length
.- Simultaneously, start a
setInterval
event handler to periodically check whether or not all of the AjaxHEAD
requests have completed.
- Simultaneously, start a
- When the
HEAD
requests have completed, begin loading the images intoImage()
objects fromimageData
, adding the associated imageContent-Length
value to thebytesLoaded
value.\ - When
bytesLoaded == bytesTotal
images are done loading, and the preloader has completed.
Here is my script as of currently:
(function($){
var callbacks = {
initiate: function(){},
progress: function(percent){},
complete: function(){},
};
var imageTemp = Array();
var imageData = Array();
var imageCurrent = null;
var intervalId = 0;
var bytesLoaded = 0;
var bytesTotal = 0;
$.preloader = function(arguments){
for(var arg in arguments){
callbacks[arg] = arguments[arg];
}
callbacks.initiate();
$('*')
.each(function(index){
if($(this).css('background-image') != 'none'){
imageTemp.push($(this).css('background-image').slice(5, -2));
}
});
intervalId = window.setInterval(function(e){
if(imageData.length == imageTemp.length){
window.clearInterval(intervalId);
for(var i = 0; i < imageData.length; i++){
(function(imageIndex){
currentImage = new Image();
currentImage.src = imageData[imageIndex][0];
currentImage.onload = function(e){
bytesLoaded += parseInt(imageData[imageIndex][1]);
callbacks.progress(bytesLoaded/bytesTotal);
if(bytesLoaded >= bytesTotal){
callbacks.complete();
}
};
})(i);
}
}
}, 1);
for(var i = 0; i < imageTemp.length; i++){
(function(i){
$.ajax({
type: "HEAD",
async: true,
url: imageTemp[i],
success: function(message, text, response){
var bytes = parseInt(response.getResponseHeader('Content-Length'));
bytesTotal += bytes;
imageData.push([imageTemp[i], bytes]);
},
});
})(i);
}
};
})(jQuery);
This is directly associated with my question over at Ajax HEAD request via Javascript/jQuery, but it certainly not a duplicate, as the issue has extended from the previously solved question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我鼓励您设置 Fiddler (或其他一些 HTTP 数据包嗅探器)并查看实际情况线路 - 发送准确的请求并收到准确的响应。这将帮助您排除问题是在服务器上还是在客户端上。
I encourage you to set up Fiddler (or some other HTTP packet sniffer) and see what is actually going through the wire - exact requests sent and exact response received. This will help you troubleshoot whether the problem is on the server or the client.
嗯,看起来很奇怪。这个“应该”有效。
我不能肯定地说这就是问题所在,但也许就是这样,我就这样说:
如果你发出 HEAD 请求,服务器本身不应该向你发送比头数据更多的数据。
几乎所有网络服务器都遵循这一点。
因此服务器出现问题的可能性不大。然而,它是可能的,具体取决于运行的应用程序。
但我在许多爬行环境和东西中多次看到这个问题,并且一个非常常见的失败点是重定向。
许多内部库遵循重定向(正如它们应该的那样),但“忘记”了 HEAD 请求。
我曾经查阅过 RFC,但不太清楚此时到底应该做什么。
但非常严格地解释 HEAD 请求应该为您提供 Location 标头。
但大多数“用户”可能期望重定向背后的头部数据。
例如 Zend ZF 直到今天仍然存在这个问题。 scrapy 在稍后的版本中修复了它。
抱歉,我无法给您更好的答案,但您的代码在这个问题上看起来是正确的,因此需要进行一些试验和错误调试...
Well it looks weird. This "should" work.
I cant say for sure this is the problem but maby it is so here I go:
If you do a HEAD request the server itself shouldnt you send you more than the head data.
Almost every webserver you can get out there honors this.
So the chances of a server issue is unlikely. However its possible, depending on the application running.
But I have seen this very issue a lot of times in in many crawling environments and stuff, and a very common point of failures were redirects.
A lot of internal libraries follow redirects (as they should) but "forget" about the HEAD request.
I once looked up the RFC but couldn't quite figure out what exactly should be done at this point.
But very strictly interpreted the HEAD request should give you the Location header.
But most "users" probably expect the head data of whatever is behind the redirect.
For example Zend ZF has this issue up til today. scrapy fixed it some later release.
Sorry I can't give you a better answer but your code looks correct regarding this issue so its some trial and error debugging...