一个关于image访问图片跨域的问题

您所在的位置:网站首页 不跨域的图片 一个关于image访问图片跨域的问题

一个关于image访问图片跨域的问题

2024-05-15 19:47| 来源: 网络整理| 查看: 265

一、背景

项目中遇到一个问题,同一个图片在 dom 节点中使用了’img’ 标签来加载,同时由于项目使用了 ThreeJS 3D 渲染引擎,在加载纹理时使用了 TextureLoader 来加载了同一张图片,而由于图片是在阿里云服务器上的,所以最后报出了如下错误,意思是在访问图片时出现了跨域问题:

二、问题梳理

2.1 关于图片的加载

图片是来自于阿里云服务器的,和本地 localhost 必然存在跨域问题。通过 dom 节点的’img’ 标签来直接访问是没有问题,因为浏览器本身不会有跨域问题。问题出在通过 TextureLoader 来加载图片时出现了跨域问题。查看了 TextureLoader 的源码,发现其进一步使用了 ImageLoader 来加载图片,加载图片的代码大致如下:

12345678910crossOrigin: 'anonymous',......var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );......if ( url.substr( 0, 5 ) !== 'data:' ) { if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;}......image.src = url;

这段代码所描述的大致思路是:

通过 JS 代码,创建一个 img 的 dom element,然后使用这个 element 来加载图片。 默认情况下,设置了 crossOrigin 的跨域属性为’anonymous’。

所以,问题的关键在于,同一张图片,先用’img’ 标签去加载了,然后再在 JS 代码中,创建一个’img’ 并且设置了 crossOrigin 的跨域属性为’anonymous’,那么在 JS 中创建的’img’ 就会出现访问图片而产生跨域的问题。

2.2 关于 crossOrigin

关于 crossOrigin,我们看看 MDN 的解释。

这段话,用我自己的理解来解释一下:

加了 crossorigin 属性,则表明图片就一定会按照 CORS 来请求图片。而通过 CORS 请求到的图片可以再次被复用到 canvas 上进行绘制。换言之,如果不加 crossorigin 属性的话,那么图片是不能再次被复用到 canvas 上去的。 可以设置的值有 anonymous 以及 use-credentials,2 个 value 的作用都是设置通过 CORS 来请求图片,区别在于 use-credentials 是加了证书的 CORS。 如果默认用户不进行任何设置,那么就不会发起 CORS 请求。但如果设置了除 anonymous 和 use-credentials 以外的其他值,包括空字串在内,默认会当作 anonymous 来处理。

2.3 问题总结

通过前面 2 点的梳理,我们得出如下结论:

通过’img’ 加载的图片,浏览器默认情况下会将其缓存起来。 当我们从 JS 的代码中创建的’img’ 再去访问同一个图片时,浏览器就不会再发起新的请求,而是直接访问缓存的图片。但是由于 JS 中的’img’ 设置了 crossorigin,也就意味着它将要以 CORS 的方式请求,但缓存中的图片显然不是的,所以浏览器直接就拒绝了。连网络请求都没有发起。 在 Chrome 的调试器中,在 network 面板中,我们勾选了 disable cache 选项,验证了问题确实如第 2 点所述,浏览器这时发起了请求并且 JS 的’img’ 也能正常请求到图片。

三、解决问题

前面通过勾选 disable cache 来避免浏览器使用缓存图片而解决了问题,但实际用户不会这样使用啊。根据前面的梳理,’img’ 不跨域请求,而 JS 中的’img’ 跨域请求,所以不能访问缓存,那么是不是可以将 JS 中的’img’ 也设置成不跨域呢,于是将 JS 中的’img’ 的 crossorigin 设置为 undefine,结果图片是可以加载了,但又得到如下错误。这段错误的意思是,这一个来自于 CORS 的图片,是不可以再次被复用到 canvas 上去的。这就验证了关于 crossorigin 中的第 1 点。既然’img’ 和 JS 中的’img’ 都不加 crossorigin 不能解决 canvas 重用的问题,那么在两边同时都加上 crossorigin 呢?果然,在’img’ 中和 JS 中的’img’ 都加上 crossorigin = “anonymous”,图片可以正常加了,同时也可以被复用到’canvas’ 上去了。另外,需要注意的 2 个小问题是:

服务器必须加上字段,否则,客户端设置了也是没用的。

Access-Control-Allow-Origin: *

如果是已经出了问题,你才看到这篇文章,或者才去想到这么解决。那么要记得先清理一下游览器所缓存的图片。否则你就会发现,有的图片可以访问,而有的不可以。那是因为缓存中之前存储了未 CORS 的图片。

四、总结

前面说了一框,只是想把这个过程完整的记录下来。整个问题的总结是:

同一张图片或者同一个地址,同时被’img’ 所访问,而随后后又会被如 JS 中去访问。而图片存储的地址是跨域的,那么就可能因为缓存问题而导致 JS 中的访问出现跨域问题。 解决的办法是让’img’ 标签和 JS 中的访问都走跨域访问的方式,这样既可以解决跨域访问的问题,也可以解决跨域图片在 canvas 中的复用。

最后,感谢你能读到并读完此文章,如果分析的过程中存在错误或者疑问都欢迎留言讨论。如果我的分享能够帮助到你,还请记得帮忙点个赞吧,谢谢。安装掘金浏览器插件打开新标签页发现好内容,掘金、GitHub、Dribbble、ProductHunt 等站点内容轻松获取。快来安装掘金浏览器插件获取高质量内容吧!https://juejin.cn/post/6844903795726483463



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3