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

news2024/11/27 2:39:01

一、背景


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

二、问题梳理

2.1 关于图片的加载

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

crossOrigin: '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;

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

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

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

2.2 关于 crossOrigin

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

 

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

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

2.3 问题总结

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

  1. 通过 'img' 加载的图片,浏览器默认情况下会将其缓存起来。
  2. 当我们从 JS 的代码中创建的 'img' 再去访问同一个图片时,浏览器就不会再发起新的请求,而是直接访问缓存的图片。但是由于 JS 中的 'img' 设置了 crossorigin,也就意味着它将要以 CORS 的方式请求,但缓存中的图片显然不是的,所以浏览器直接就拒绝了。连网络请求都没有发起。
  3. 在 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 个小问题是:

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

Access-Control-Allow-Origin: *

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

四、总结


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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SourceTree 拉取、重置提交、回滚、变基与合并

SourceTree的重置当前分支到此次提交 使用场景:“我想把已提交未推送的修改撤销” 使用模式说明软合并软合并是指将此次提交回滚到指定提交位置,但这个过程中会将修改过的文件暂存到暂存区。混合合并混合合并是指将此次提交回滚到指定的位置&#xff0c…

本来挺喜欢刷《剑指offer》的.......(第十一天)

跟着博主一起刷题 这里使用的是题库: https://leetcode.cn/problem-list/xb9nqhhg/?page1 目录剑指 Offer 66. 构建乘积数组剑指 Offer 68 - I. 二叉搜索树的最近公共祖先剑指 Offer 68 - II. 二叉树的最近公共祖先剑指 Offer 66. 构建乘积数组 剑指 Offer 66. 构建…

使用react-bmapgl绘制区域并判断是否重叠

需求如下: 在react项目中使用百度地图实现区域(电子围栏)的绘制绘制的区域类型为:1、多边形 2、圆形可绘制多个区域区域不能有重叠可重新编辑区域 代码如下: index.tsx import { useCallback, useEffect, useState } from rea…

Python入门实践(二)——变量的使用

文章目录变量1、变量的命名和使用1.1、避免命名错误2、字符串2.1、修改字符串大小写2.2、合并(拼接)字符串2.3、使用制表符或换行符来添加空白2.4、删除空白3、数字3.1、整数3.2、浮点数3.3、使用str()避免类型错误4、注释变量是对一种数据结构的命名&am…

2023年基建工程(设计规划施工)经验分享,超多干货

为了彻底打通从工程外业勘探调查、数据资料整理,到内业详细设计之间的一系列障碍,结合工程外业调查的特点,基于安卓(Android)操作系统,精心打磨推出了“外业精灵”移动端应用软件。 该系统把工程外业探勘、…

MPP数据库简介及架构分析

目录什么是MPP?特性并行处理超大规模数据仓库真正适合什么典型的分析工作量数据集中化线性可伸缩性MPP架构技术特性数据库架构分析Shared EverythingShared DiskShare MemoryShared NothingShared Nothing数据库架构优势什么是MPP? MPP (Massively Paral…

分享88个C源码,总有一款适合您

C源码 分享88个C源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下...,大家下载后可以看到。 源码下载链接:https://pan.baidu.com/s/1TT87gt66kn5BtLqgRUTlUQ?pwdwje5 提取码…

Java图形化界面---JOptionPane

目录 一、JOptionPane的介绍 二、JOptionalPane的使用 (1)消息对话框 (2) 确认对话框 (3)输入对话框 (4)选项对话框 一、JOptionPane的介绍 通过JOptionPane可以非常方便地创建…

SpringCloud复习之Sleuth+Zipkin链路追踪实战

文章目录写作背景为什么要有链路监控SpringCloud SleuthZipkin能做什么上手实战启动一个Zipkin Server微服务集成SleuthZipkin写作背景 前面复习了SpringCloud Netflix的几个核心组件,包括Eureka、Ribbon、Feign、Hystrix、Zuul,并进行了Demo级别的实战…

高精度减法【c++】超详细讲解

前言 大家学过高精度加法之后,可能已经知道高精度减法的实现方法了吧 如果你还没有学过高精度加法的话,请点击这里(很详细的)—>高精度加法【C实现】详解 最大的问题 最大的问题莫过于负数问题了。其他方法和加法一样。 负…

4.二级缓存解析

文章目录1. 二级缓存配置2. 二级缓存结构3. 二级缓存命中条件4. 缓存空间的理解5. 二级缓存执行流程二级缓存也称作是应用级缓存,与一级缓存不同的,是它的作用范围是整个应用,而且可以跨线程使用。所以二级缓存有更高的命中率,适合…

从南丁格尔图到医学发展史

可视化中,前端用于表现不同类目的数据在总和中的占比的场景,往往会采用饼图。 针对数据大小相近,南丁格尔图的呈现会更加美观。 南丁格尔图,又称玫瑰图,是由弗罗伦斯南丁格尔发明。 弗洛伦斯南丁格尔 开创了护理事业…

二、django中的路由系统

django中的路由系统 django中路由的作用和路由器类似,当一个用户请求Django站点的一个页面时,是路由系统通过对url的路径部分进行匹配,一旦匹配成功就导入并执行对应的视图来返回响应。 django如何处理请求 当一个请求来到时,d…

SpringSecurityOauth2架构Demo笔记

总体分为SpringSecurityOauth2授权码模式演示和密码模式演示 一直下一步,依赖手动导入,SpringBoot版本改成2.2.5.RELEASE,JDK版本1.8 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xml…

Open3D 点云投影至指定球面(Python版本)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 假设球体的相关参数:中心为 C ( x c , y c , z c ) C(x_c,y_c,z_c)

【数据结构和算法】栈—模拟实现Stack和栈相关算法题

文章目录栈的定义Stack模拟实现相关算法题1.栈的压入弹出序列2.逆波兰表达式(后缀表达式)⭐1.什么是逆波兰表达式?如何转换成逆波兰表达式逆波兰表达式如何计算3.有效的括号总结栈的定义 栈作为一种数据结构&#xff0c;是一种只能在一端进行插入和删除操作的特殊线性表。它按…

华为MPLS跨域C2方案实验配置

MPLS隧道——跨域解决方案C1、C2讲解_静下心来敲木鱼的博客-CSDN博客_route-policy rr permit node 10 if-match mpls-labelhttps://blog.csdn.net/m0_49864110/article/details/127634890?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId…

深度学习——长短期记忆网络LSTM(笔记)

长短期记忆网络LSTM&#xff1a; ①隐变量模型存在长期信息保存和短期输入缺失问题&#xff0c;解决方法是LSTM ②发明于90年代 ③使用效果和GRU差别不大&#xff0c;但是实现起来复杂 1.长短期记忆网络 ①忘记门Ft&#xff1a;将值朝0减少 ②输入门It&#xff1a;是否忽…

最容易理解的并查集详解

并查集 并查集&#xff0c;在一些有N个元素的集合应用问题中&#xff0c;我们通常是在开始时让每个元素构成一个单元素的集合&#xff0c;然后按一定顺序将属于同一组的元素所在的集合合并&#xff0c;其间要查找一个元素在哪个集合中。 比如下面这幅图&#xff0c;总共有 10 …

MySQL之存储过程

MySQL存储过程1、基本介绍1.1、介绍存储过程&#xff1a;1.2、特点1.3、基本语法1.3.1、delimiter1.3.1、创建存储过程1.3.2、调用存储过程1.3.3、查看存储过程1.3.4、删除存储过程2、变量2.1、系统变量2.1.1、查询(会话、全局、模糊、精确)2.1.2、设置系统变量2.2、用户定义变…