j7n*_*n7k 25 javascript http-status-code-404 retina.js
我们使用js lib retina.js,它将低质量图像与"视网膜"图像交换(大小乘以2).问题是,retina.js为每个无法找到的"视网膜"图像抛出404.
我们拥有一个网站,用户可以上传他们自己的图片,这些图片很可能不是视网膜分辨率.
有没有办法阻止js投掷404s?
如果你不知道lib.这是抛出404的代码:
http = new XMLHttpRequest;
http.open('HEAD', this.at_2x_path);
http.onreadystatechange = function() {
if (http.readyState != 4) {
return callback(false);
}
if (http.status >= 200 && http.status <= 399) {
if (config.check_mime_type) {
var type = http.getResponseHeader('Content-Type');
if (type == null || !type.match(/^image/i)) {
return callback(false);
}
}
RetinaImagePath.confirmed_paths.push(that.at_2x_path);
return callback(true);
} else {
return callback(false);
}
}
http.send();
Run Code Online (Sandbox Code Playgroud)
tif*_*fon 28
我看到了一些选项来减轻这种情况.
对于设置为换出"1x"版本的任何给定"2x"图像,retina.js首先通过XMLHttpRequest请求验证图像的可用性.成功响应的路径缓存在数组中,并下载映像.
以下更改可能会提高效率:
XMLHttpRequest可以缓存失败的验证尝试:目前,只有先前成功的'2x'路径验证尝试才会被跳过.因此,失败的尝试可能会再次发生.在实践中,这与初始加载页面时验证过程发生的情况无关.但是,如果结果持续存在,跟踪故障将防止重复出现404错误.
持续'2x'路径验证结果为localStorage:在初始化期间,retina.js可以检查localStorage结果缓存.如果找到一个,则可以绕过已经遇到的"2x"图像的验证过程,并且可以下载或跳过"2x"图像.可以验证新遇到的"2x"图像路径,并将结果添加到缓存中.从理论上讲,虽然localStorage可用,但每个浏览器的图像只会出现一次404.这将适用于域上任何页面的页面.
这是一个快速的检查.可能需要添加到期功能.
https://gist.github.com/4343101/revisions
我必须指出,我对"服务器端"问题的把握充其量只是参差不齐.请带上这个FWIW
另一个选项是服务器使用重定向代码来响应具有@2x字符且不存在的图像请求.看到这个相关的答案.
特别是:
如果您重定向图像并且它们是可缓存的,那么理想情况下,您可以在遥远的未来为日期设置HTTP Expires标头(以及相应的Cache-Control标头),因此至少在后续访问页面时用户不会再次进行重定向.
使用重定向响应将消除404并导致浏览器跳过后续尝试访问不存在的"2x"图像路径.
可以修改视网膜以排除一些图像.
与此相关的拉取请求:https://github.com/imulus/retinajs/commit/e7930be
根据pull请求,不是<img>按标签名称查找元素,而是可以使用CSS选择器,这可以是retina.js的可配置选项之一.可以创建一个CSS选择器,用于过滤掉用户上传的图像(以及预期不存在'2x'变体的其他图像).
另一种可能性是为可配置选项添加过滤功能.可以在每个匹配的<img>元素上调用该函数; a return true会导致下载'2x'变体,其他任何东西都会导致<img>跳过.
基本的默认配置会从当前版本更改为:
var config = {
check_mime_type: true,
retinaImgTagSelector: 'img',
retinaImgFilterFunc: undefined
};
Run Code Online (Sandbox Code Playgroud)
该Retina.init()函数将从当前版本更改为:
Retina.init = function(context) {
if (context == null) context = root;
var existing_onload = context.onload || new Function;
context.onload = function() {
// uses new query selector
var images = document.querySelectorAll(config.retinaImgTagSelector),
retinaImages = [], i, image, filter;
// if there is a filter, check each image
if (typeof config.retinaImgFilterFunc === 'function') {
filter = config.retinaImgFilterFunc;
for (i = 0; i < images.length; i++) {
image = images[i];
if (filter(image)) {
retinaImages.push(new RetinaImage(image));
}
}
} else {
for (i = 0; i < images.length; i++) {
image = images[i];
retinaImages.push(new RetinaImage(image));
}
}
existing_onload();
}
};
Run Code Online (Sandbox Code Playgroud)
在window.onload火灾发生之前,请致电:
window.Retina.configure({
// use a class 'no-retina' to prevent retinajs
// from checking for a retina version
retinaImgTagSelector : 'img:not(.no-retina)',
// or, assuming there is a data-owner attribute
// which indicates the user that uploaded the image:
// retinaImgTagSelector : 'img:not([data-owner])',
// or set a filter function that will exclude images that have
// the current user's id in their path, (assuming there is a
// variable userId in the global scope)
retinaImgFilterFunc: function(img) {
return img.src.indexOf(window.userId) < 0;
}
});
Run Code Online (Sandbox Code Playgroud)
更新:清理并重组.添加了localStorage增强功能.
简短回答:仅使用客户端JavaScript是不可能的
在浏览代码和一些研究之后,在我看来,retina.js并没有真正抛出404错误.
retina.js实际上正在做的是请求一个文件,只是根据错误代码检查它是否存在.这实际上意味着它要求浏览器检查文件是否存在.浏览器是给你404的东西,没有跨浏览器的方式来阻止它(我说"跨浏览器",因为我只检查了webkit).
但是,如果这确实是一个问题,你可以做的是在服务器端做一些事情来完全防止404s.
基本上这将是,例如,/retina.php?image = YOUR_URLENCODED_IMAGE_PATH一个请求,当视网膜图像存在时,可以返回此请求...
{"isRetina": true, "path": "YOUR_RETINA_IMAGE_PATH"}}
Run Code Online (Sandbox Code Playgroud)
如果它不...
{"isRetina": false, "path": "YOUR_REGULAR_IMAGE_PATH"}}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用一些JavaScript调用此脚本并根据需要解析响应.我并不是说这是唯一或最好的解决方案,只是一个可以工作的解决方案.
Retina JS支持图像标签上的属性data-no-retina.这样它就不会试图找到视网膜图像.
寻找简单解决方案的其他人很有帮助.
<img src="/path/to/image" data-no-retina />
Run Code Online (Sandbox Code Playgroud)