• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

项目中的图片跨域问题解决方式

互联网 diligentman 2周前 (11-18) 5次浏览

现象

首先,在生产环境中,由于进行编辑图片时,将图片回显到ReactCrop组件中进行可裁剪编辑,然而回显时,需要将图片转化为base64的格式或者blob对象, 此时需要将图片次绘制成canvas进行裁剪,但是,就会出现图片的跨域问题,图片不在一个域下的话,使用 canvas 会污染画布,所以就不行啦!!!!
不过这个其实是需要后端在服务端进行配置就好了,但是前端要硬抗的话,那只能含着泪解决吧!

解决方案一

因为在本地进行图片回显的时候就已经跨域了,所以为了保证在同一域的环境进行处理图片显示的问题。

Mac

  • 设置打开Chorme跨域浏览器指令:
open -n /Applications/Google Chrome.app/ --args --disable-web-security  --user-data-dir=/Users/${电脑用户名}/MyChromeDevUserData/

注意: 运行命令之前,必须得彻底关闭当前chorme浏览器。
例如:open -n /Applications/Google Chrome.app/ –args –disable-web-security –user-data-dir=/Users/gml/MyChromeDevUserData/

Windows

  • Chrome 49 以后版本
 --disable-web-security --user-data-dir=<用户数据路径> --allow-file-access-from-files
  • 完整例子
C:UsersAdministratorAppDataLocalGoogleChromeApplicationchrome.exe --disable-web-security --user-data-dir=C:MyChromeDevUserData --allow-file-access-from-files
  • 创建 Chrome 快捷方式,在目标一栏后面添加参数即可

项目中的图片跨域问题解决方式
以上是设置跨域浏览器的教程。下面回归正题

getBase64 = (url, callback)=> {
    const urlReplace = url.replace('http', 'https');
    //通过构造函数来创建的 img 实例,在赋予 src 值后就会立刻下载图片,相比 createElement() 创建 <img> 省去了 append(),也就避免了文档冗余和污染
    /*let img = new Image(),
      dataURL = '';
    img.crossOrigin = "Anonymous";
    img.src = url;

    img.onload = function () { //要先确保图片完整获取到,这是个异步事件
      let canvas = document.createElement('canvas'), //创建canvas元素
        width = img.width, //确保canvas的尺寸和图片一样
        height = img.height;
      canvas.width = width;
      canvas.height = height;
      canvas.getContext('2d').drawImage(img, 0, 0, width, height); //将图片绘制到canvas中
      dataURL = canvas.toDataURL('image/jpeg'); //转换图片为dataURL
      callback && callback(dataURL); //调用回调函数
    };*/

    console.log('urlReplace', urlReplace)
    const _this = this;

    axios.get(urlReplace,
      {
      responseType: 'blob',
      headers: { "Access-Control-Allow-Origin": "*" }
      }
      ).then(function (response) {
        console.log('response', response)
      _this.callBack(response);
      })

  }

  callBack(res){
    let blob = new Blob([res]);
    let url = window.URL.createObjectURL(blob);
    console.log('url', url);

    this.setState({
      src: url
    })
    // 释放url对象
    // window.URL.revokeObjectURL(url);
  }

以上的原始代码在在转化base64时,需要canvas重绘图片,进行生成base64图片格式进行接收,也就是toDataURL()是canvas对象的一种方法,用于将canvas对象转换为base64位编码,但是出现是canvas.tuDataUrl的跨域问题。

  • 将图片转换为base64位编码有什么好处?

1、将图片转换为base64位编码后,图片会跟随代码(html、css、js)一起请求加载,不会再单独进行请求加载; 2、可以防止由于图片路径错误导致图片加载失败的问题;

使用canvas.toDataUrl跨域的解决方式就是在设置img.crossOrigin = “Anonymous”; 方法。然后在服务器端设置请求头"Access-Control-Allow-Origin": “*”。然而在生产环境并无效果。所以避开canvas的跨域问题只能重新更换方案。

补充:

  • img元素中的crossorigin属性

img是我们在web开发中比较常用的一个标签,它代表着文档中的一个图像元素。HTML5给这个标签新增加了一个crossorigin属性,这个属性决定了图片获取过程中是否开启CORS功能

使用场景

在最近的项目开发中,在前端预览图片并让用户裁剪,再将裁剪好的图片上传到后端的服务器上。这里输入的图片地址很有可能来自第三方站点,这就涉及到一个跨域的问题,如果仅仅是展示预览图片的话是没有什么问题的,但这里裁剪图片时需要将裁剪好的图片进行base64编码,如果没有使用crossorign开启CORS功能的话,在使用canvas的toBlob()、toDataURL()和getImageData()方法时就会出现跨域的问题。

crossorigin属性

这个属性有两个值可选:
anonymous:如果使用这个值的话就会在请求中的header中的带上Origin属性,但请求不会带上cookie和其他的一些认证信息。
use-credentials:这个就同时会在跨域请求中带上cookie和其他的一些认证信息。
在使用这两个值时都需要server端在response的header中带上Access-Control-Allow-Credentials属性。

虽然 已经设置但是在生产环境还未生效。这可能是后端的锅了,不过后端一直没有改好的情况下,前端只能硬着头皮去抗下啦。还好经过百般尝试后,出来了解决方案:

getBase64 = (url, callback)=> {
    const urlReplace = url.replace('http', 'https');
    const _this = this;
    axios.get(urlReplace,
      {
      responseType: 'blob',
      headers: { "Access-Control-Allow-Origin": "*" }
      }
      ).then(function (response) {
        console.log('response', response)
      _this.callBack(response);
      })

  }

  callBack(res){
    let blob = new Blob([res]);
    let url = window.URL.createObjectURL(blob);
    console.log('url', url);

    this.setState({
      src: url
    })
    // 释放url对象
    // window.URL.revokeObjectURL(url);
  }

以上代码通过axios请求图片路径并且加上请求头的条件,然后返回结果生成Blob对象,然后再创建 URL 的blob对象,赋值到裁剪的组件里进行实时裁剪。

总结:

以上尝试的结果,也是避开canvas的跨域问题,另起炉灶开辟了新的方案,才解决了跨域的根本问题。不过解决办法还有其他方式,后续可以深入研究

以上解决的问题中涉及的知识点也蛮多的:

  1. canvas的toDataUrl跨域问题canvas的toDataUrl跨域问题
  2. crossorigin属性 crossorigin
  3. Cross-Origin Resource Sharing(CORS)解决方案CORS
  4. axios的请求方式 axios
  5. toDataURL()方法 toDataURL()方法

喜欢 (0)