图片下载本地报跨域

kingcwt2021-9-30前端react

一、 背景


在开发的附件下载组件中,后端返回的图片链接无法使用a标签添加download属性下载本地,只能在另一个窗口打开。所以为了解决产品提出的这个需求。 我采用fetch请求的方式下载到本地。然后遇到了图片报错跨域问题。

报错信息: 图片跨域报错图

二、 问题梳理


2.1 关于图片下载的方法

从报错信息上看,就是图片下载的时候出现跨域头的问题,于是联系了后端。后端竟然说不知道怎么设置。还要找他们的组长看。于是为了解决这个问题。 我在网上查找了很多种方法。起初用fetch,设置mode,发现不报跨域的错了。但是无法拿到请求的资源,甚至有时候可以下载本地。有时候不可以。然后又采用了转二进制,转base64,以及使用canvas等。最后发现都不行。最后在网上看到有人说是缓存的问题。于是,我就清除缓存试了试,发现问题一下解决了。

2.2 问题概括

因为封装的附件下载组件支持所有格式的文件预览,在预览的同时就会去渲染这个图片链接,通过img标签展示出来。通过 'img' 加载的图片,浏览器默认情况下会将其缓存起来。当我再去请求这个链接的时候,因为缓存中已经存在啦。所以浏览器直接拒绝,报错跨域。

三、 解决问题


因为在预览的时候,我已经请求一次这个图片地址并用来展示,而当我才用fetch请求的时候,因为img默认没有设置跨域请求属性,而我的fetch请求是属于跨域请求 ,所以,只要在img标签上加上crossOrigin="anonymous"采用跨域请求资源。这个时候。当我们再去跨域请求的时候就不会被浏览器拒绝。

四、 总结


  1. 我们要弄清楚问题的原因所在。在这里一种是后端没有设置跨域头的问题。这个需要后端设置。一种是我们本地缓存问题造成的跨域。 所以如果你已经看到这里了,要冷静思考。问题的原因所在。如果有的图片可以下载,有的图片不可以下载,那你就打开前端控制台。点击Network选项卡。勾选Disble cache,意思是不缓存。然后你在点击下载。看看是不是可以下载。如果可以下载。那就是本地缓存的问题无疑。看看是不是用到了img标签。

  2. 在这里:如果像我这种问题。fetch请求跨域图片地址。img展示的时候也要相应的设置crossOrigin="anonymous",都采用跨域请求。才不会跨域。

五、 附上我的完整代码

5.1 图片设置跨域属性

<img height={650} src={url} crossOrigin="anonymous" role="presentation" />

5.2 js请求的方法


/**
   * 图片下载到本地
   * @param {string} name 图片名称
   * @param {string} url  图片地址
   * 解决图片资源请求跨域问题
   */
  downloadWithBlob(name, url) {
    /* 常见资源类型
    1.excel: type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    2.图片: type = "image/*"
    3.视频: type = "video/*"
    4.音频: type = "audio/*"
    */
    window.fetch(url, {
      mode: 'cors',
    }).then((response) => {
      // 拿到arrayBuffer 转化为 blob 生成链接  通过a标签打开
      response.arrayBuffer().then((res) => {
        const type = 'image/*';  // 资源类型
        // eslint-disable-next-line no-undef
        const blob = new Blob([res], { type });
        const objectUrl = window.URL.createObjectURL(blob);
        const a = window.document.createElement('a');
        window.document.body.appendChild(a);
        a.style = 'display: none';
        a.href = objectUrl;
        a.download = name;
        a.click();
        window.document.body.removeChild(a);
      });
    });
  }

最后,感谢你能读到并读完此文章,如果分析的过程中存在错误或者疑问都欢迎留言讨论。如果我的分享能够帮助到你。麻烦github 点波关注。🚗。

Last Updated 10/16/2023, 7:06:22 AM
What do you think?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v2.15.8