html转pdf 图片跨域问题解决

之前文章说了, 我这边图片是阿里云的地址, 默认在页面 分页 用Img标签展示, 点击导出的时候再请求一次后端拿回全部 数据 展示(这里展示是定位到其他地方,不遮住原来页面, 然后导出完毕这个页面就销毁了这样 ) , 这时导出就报跨域了.

1. 问题分析:

这里来自这位大佬分析, 我场景差不多也是这样.
https://www.jianshu.com/p/8fa0fb53c183 一个关于image访问图片跨域的问题

也就是我页面 一开始就默认 展示一次图片了, 后面又通过js 导出pdf方式使用这个 图片, 导致跨域了, 那么按照这个说法, 应该就是 转pdf过程中, 对图片处理使用了 crossOrigin 属性,导致请求会跨域.下面是他的说法:
截取大佬的

2. 关于crossOrigin

在这里插入图片描述

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

2.3 问题总结

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

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

三、解决问题

前面通过勾选 disable cache 来避免浏览器使用缓存图片而解决了问题,但实际用户不会这样使用啊。根据前面的梳理, 不跨域请求,而 JS 中的 跨域请求,所以不能访问缓存,那么是不是可以将 JS 中的 也设置成不跨域呢,于是将 JS 中的 的 crossorigin 设置为 undefine,结果图片是可以加载了,但又得到如下错误。
在这里插入图片描述

这段错误的意思是,这一个来自于CORS 的图片,是不可以再次被复用到 canvas 上去的。这就验证了关于 crossorigin 中的第 1 点。

既然 和 JS 中的 都不加 crossorigin不能解决 canvas 重用的问题,那么在两边同时都加上 crossorigin 呢?果然,在 中和 JS 中的 都加上 crossorigin = “anonymous”,图片可以正常加了,同时也可以被复用到 上去了。

另外,需要注意的 2 个小问题是:

扫描二维码关注公众号,回复: 13483912 查看本文章

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

Access-Control-Allow-Origin: *

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

四、总结

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

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

五. 我的使用

上面几点都是大佬说的,复制过来大家看看, 那么问题清楚了 , 就去解决!!
我这边处理是 所有图片 都加上 crossOrigin:‘anonymous’, 但是发现有图片 第一次请求失败,后面就成功了,不知道为啥
后来我就改成 用户分页 选择了多少条就导出多少条, 不像之前导出就全部导出来,这样就会存在有图片第一次没成功.
所以, 改成 用户分页 选择了多少条就导出多少条, 这样没问题,最终就先这样解决了.

 setImgCros(id) {
    
    
      // 处理图片跨域
      const element = document.getElementById(id);
      let imgList = element.getElementsByTagName("img");
      console.log("imglist", imgList);
      if (imgList.length > 0) {
    
    
        for (let i = 0; i < imgList.length; i++) {
    
    
            imgList[i].setAttribute("crossOrigin", "anonymous");
        }
      }
    },

这样,导出前先设置跨域属性.

 await this.getPdfList();
        this.$nextTick(async () => {
    
    
          // 设置跨域请求
          // 设置原因: 同一张图片或者同一个地址,同时被 <img> 所访问,而随后后又会被如 JS 中去访问。而图片存储的地址是跨域的,那么就可能因为缓存问题而导致 JS 中的访问出现跨域问题。所以都设置成跨域请求
          this.setImgCros('pdf-position')
          this.$message({
    
    
            type: "info",
            message: "正在导出中,请稍等...",
            showClose: true,
            duration: 3000,
          });
          //  return
          // 延迟一会在下载, 因为解析有生成二维码的是异步,需要等待二维码生成
          setTimeout(() => {
    
    
          htmlToPdf("pdf-position", "下载文件")
            .then(() => {
    
    
              this.downloadLoading = false;
              this.pdfList = [];
              this.$message({
    
    
                type: "success",
                message: "导出成功!",
              });
            })
            .catch(() => {
    
    
              this.$message({
    
    
                type: "error",
                message: "PDF下载失败",
              });
              this.downloadLoading = false;
              this.pdfList = [];
            });
          }, 300)

猜你喜欢

转载自blog.csdn.net/weixin_45295262/article/details/120676759