需求场景:上传图片后接口返回文件id,展示图片时链接地址为/file/preview?id=xxx。但系统中的接口都需要鉴权(即在请求header中添加authCode),而img标签的请求是浏览器的默认行为,并不受我们的接口拦截(如axios请求拦截)约束。

通常的解决方式:

手动发请求+处理流

Vue为例,我们可以封装一个自定义图片组件authImg

<template><img ref="img">
</template>
<script>
export default {props:{src:{type: String,default:''}},watch:{src:{handler(n){if(n){this.getImage(n);}},immediate:true}},methods:{getImage(url){let that = this;that.$nextTick(()=>{let request = new XMLHttpRequest();request.responseType = 'blob';request.open('get', url, true);// 添加自定义请求头request.setRequestHeader('authToken', localStorage.getItem('authToken')); request.onreadystatechange = e => {if (request.readyState == XMLHttpRequest.DONE && request.status == 200) { that.$refs.img.src = URL.createObjectURL(request.response);that.$refs.img.onload = () => {that.$refs.img && URL.revokeObjectURL(that.$refs.img.src);} }};request.send(null);});}}
}
</script>

使用:

<template><authImg src="/file/preview?id=xxx"></authImg>
</template>

此方式可以处理绝大多数场景,但解决不了类似富文本中的img问题。一般富文本会保存成字符串,数据回显时,很难处理其中的img标签

通过自定义元素加载

这种方式就是扩展原有的HTML Element,实现一些自定义的功能,示例如下

// 扩展原生Image
let requestImage = function (url, element) {let request = new XMLHttpRequest();request.responseType = 'blob';request.open('get', url, true);request.setRequestHeader('authToken', localStorage.getItem('authToken')); request.onreadystatechange = e => {if (request.readyState == XMLHttpRequest.DONE && request.status == 200) {element.src = URL.createObjectURL(request.response);element.onload = () => {element && URL.revokeObjectURL(element.src);}}};request.send(null);
}class AuthImg extends HTMLImageElement {constructor() {super();this._lastUrl = '';}static get observedAttributes() {return ['authsrc'];}connectedCallback() {let url = this.getAttribute('authsrc');if (url !== this._lastUrl) {this._lastUrl = url;requestImage(url, this);}console.log('connectedCallback() is called.');}
}
window.customElements.define('auth-img', AuthImg, {extends: 'img'});

使用:

原始(报错401):<img src="/file/preview?id=xxx">
替换后:<img is="auth-img" authsrc="/file/preview?id=xxx"/>

此方式可以解决上述的富文本中的图片问题,以wangEdit为例

// 自定义上传图片
this.editor.customConfig.uploadImgHooks = {customInsert: function (insertImg, result, editor) {let imgUrl = result.data[0];that.editor.cmd.do('insertHTML', `<img is="auth-img" authsrc="${imgUrl}" alt="图片" /> `);}
}
serviceWorker

我们真的没办法拦截到浏览器原生的img请求吗?其实是可以的。serviceWorker具体使用可自行查找资料,这里我们简单做个示例:

<!--index.html-->
<script>
if ('serviceWorker' in navigator) {navigator.serviceWorker.register('./sw.js');
}
</script>
//sw.js
self.addEventListener('fetch', function (evt) {// 拦截指定请求前缀if (evt.request.url.indexOf('image/view?id')>-1) {// 拷贝原始请求const request = evt.request.clone();// 创建headersconst headers = new Headers();// 添加自定义请求头headers.append('authToken', '7c5c90e6-bf49-47c0-bda1-bc93255364d8'); // 创建新请求const newRequest = new Request(request,{headers,mode: 'cors'})// 返回=>走浏览器原有逻辑evt.respondWith(fetch(newRequest))}
});

这样我们就不需要修改img标签,或者做其它处理。通过serviceWorker自动拦截对应请求,添加请求头,剩下的交给浏览器就可以了。

后记

第一、二种方式原则上差不多,第二种覆盖场景会多一些,但改动量都比较大。

第三种方式改动较小,基本上是全场景覆盖,如富文本,如css背景图设置成接口地址;但自定义性较差,比如异常回调,加loading之类的操作。

当然使用serviceWorker,同样可以对以window.open或者window.location.href形式的下载链接拦截,添加自定义请求头,就不需要前端通过调用接口获取文件流再手动转换了。

img标签请求 添加自定义header(一)相关推荐

  1. 如何给img标签里的请求添加自定义header

    是这样的需求,有一个web页面,里面图片的上传和预览来自于一个独立的文件服务器,对http的请求需要进行访问权限的设置,就是在请求的header里加一个Authorization的字段.上传好说我用的 ...

  2. img标签请求拦截_如何给img标签里的请求添加自定义header?

    是这样的需求,有一个web页面,里面图片的上传和预览来自于一个独立的文件服务器,对http的请求需要进行访问权限的设置,就是在请求的header里加一个Authorization的字段.上传好说我用的 ...

  3. 如何给img标签里的请求的添加自定义header

    如何给img标签里的请求添加自定义header 是这样的需求,有一个web页面,里面图片的上传和预览来自于一个独立的文件服务器,对http的请求需要进行访问权限的设置,就是在请求的header里加一个 ...

  4. 前端cookie 放到请求头_ajax请求携带cookie和自定义请求头header(跨域和同域)

    错误: 1.ajax请求时是不会自动带上cookie的,要是想让他带上的话,必须设置withCredential为true. 正确: 1.ajax同域请求下,ajax会自动带上同源的cookie: 2 ...

  5. vue中a标签实现带header的下载

    简单介绍一下,这个是想用a标签请求接口下载文件,请求接口动态添加header请求头 1.在按钮上添加点击事件 <el-button type="backinfo" size= ...

  6. http请求报头header

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 http 请求报头header 一.认识请求报头(header) 1.Host 2.content-length 3.content- ...

  7. java http head 请求_http请求头header、请求体body、请求行介绍

    HttpServletRequest对象代表客户端的请求,当客户端通过http协议请求访问 服务器的时候,http请求头的所有信息都封装在这个对象中,通过这个对象,可以获取客户端请求的所有信息.htt ...

  8. 解决通过Nginx转发的服务请求头header中含有下划线的key,其值取不到的问题

    解决通过Nginx转发的服务请求头header中含有下划线的key,其值取不到的问题 参考文章: (1)解决通过Nginx转发的服务请求头header中含有下划线的key,其值取不到的问题 (2)ht ...

  9. php 打印curl请求的header信息和返回的header信息

    1.打印curl请求的header信息 在执行curl请求curl_exec($ch)前的代码中,添加如下配置: //设置为true时追踪句柄的请求字符串,从 PHP 5.1.3 开始支持,就是允许你 ...

最新文章

  1. python 十大经典排序算法
  2. 解决dubbo问题:forbid consumer(2)
  3. 制约RFID在包装领域的规模应用的障碍盘点
  4. Jquery给基本控件的取值、赋值
  5. netapp学习(五)---创建volume
  6. tr69 GatewayInfo 节点添加
  7. linux path 文件,linux基础,文件目录管理,PATH,cp,mv,cat
  8. 关于React的一切(updating...)
  9. 浅谈技术管理之个体能力建设
  10. [转载]IEEE754标准的浮点数表示
  11. 阻塞与非阻塞都是什么呢?
  12. 向iis注册framework命令
  13. html 可换行属性,html里title属性换行的方法
  14. 像中文的罗马音字体复制_罗马音字体复制下载
  15. 双系统中Ubuntu启动失败
  16. android tv 盒子,安卓TV电视盒子推荐软件一览表(盒子端+手机端+电脑端+群晖端)...
  17. mac:系统存在两个Macintosh HD是怎么回事
  18. php容器概念,PHP容器——Pimple运行流程浅析
  19. 【HEOI2013】bzoj3168 钙铁锌硒维生素
  20. 洛谷 P4544 [USACO10NOV]Buying Feed G)(单调队列优化DP)

热门文章

  1. 开课吧:未来人工智能发展前景如何呢?
  2. 批量提取文件夹中文件 目录、文件名、大小(备忘)
  3. 设计一个接口, 并设计一个实现类实现该接口,演示它们的使用。具体,创建一个名称为Person的接口,在接口中定义两个方法sayHello()和sayBye()。
  4. win10连接共享打印机。同时解决电脑出现“你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访
  5. 论文解读:门控时钟的gating ratio如何提升
  6. 自学Node--回调地狱
  7. 【PIC单片机】2.编译器下载
  8. Climbing-stairs
  9. 解网鼎杯一道web题(fakebook)
  10. canvas图片文字合成(小程序分享)