<img 标签预览图片如何携带token进行验证
前言 vue中给img的src添加token
因项目中安全测评的需要,请求图片时要求添加token,方法如下:在项目中循环渲染的img标签中的图片要显示,src需要加请求头token(正常情况下,后端直接返回src的url)
图片在前端开发中扮演了重要的角色,它们不仅仅是美观的元素,还可以传递信息和激发用户的兴趣。随着应用场景的增多,前端开发人员就需要在图片加载过程中携带验证的信息。如 token,用于身份验证、权限控制等方面。通过在图片的 URL 或请求头中携带 token 信息,从而实现图片信息的安全传输。
实现思路
- 1、在img 请求图片时要求添加token:src 后 url?token=‘’ 拼接, 或通过设置在请求头里,可以使用XMLHttpRequest
- 2、间接通过一个后端api 下载文件到本地
尝试 第1方案
vue中给img的src添加token
- 自定义子组件AuthImg,在这发送请求,获取img地址
<template><div><!-- 显示图片 --><img ref="img" :style="{width:width,height:height}" v-if="imgType == 'view'" /><!-- 使用element-ui的el-image进行图片预览 --><el-image :style="{width:width,height:height}" ref="previewimg" v-if="imgType == 'preView'" :src="previewpath":preview-src-list="previewList"></el-image></div>
</template><script>import {getToken} from "@/utils/auth";export default {name: 'AuthImg',props: {imgSrc: String,// 图片类型,可选为'view'(仅预览图片)或'preView'(可点击预览)imgType: {type: String,default: "view",},// 图片的宽度width: {type: String,},// 图片的高度height: {type: String,},},data() {return {// 预览图片列表previewList: [],// 预览图片路径previewpath: "",};},computed: {// 拿到token值,登录成功后由后台返回的token() {// 这里我把登录之后拿到的token放到了vuex中return getToken();}},mounted() {},methods: {// 携带token请求img的srcgetImgSrcByToken() {// Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象Object.defineProperty(Image.prototype, 'imgSrc', {// 可写writable: true,// 可枚举enumerable: true,// 若configurable设为false,那就不可以delete了configurable: true});let img = this.$refs.img;let request = new XMLHttpRequest();request.responseType = 'blob';request.open('get', this.imgSrc, true);request.setRequestHeader('Authorization', 'Bearer ' + this.token);request.onreadystatechange(e => {if(request.readyState == XMLHttpRequest.DONE && request.status == 200) {// URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象URL,这个新的URL对象表示指定的File对象或blob对象img.src = URL.createObjectURL(request.response);img.onload = () => {// 在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放。URL.revokeObjectURL(img.src);}}});request.send(null);},},
}
</script>
- 父组件中调用
<authImg :imgSrc="baseurl + '/download.do?id='+ files.name + '&height=60'" alt=""></authImg>
下面尝试 第2方法:
- 创建一个名为 tokenImg 的组件,该组件用于显示图片并支持预览功能;
- 在组件的模板中,使用 标签来显示图片,或使用 element-ui 的 标签进行图片预览;
- 在组件的属性中,接收图片的 URL 地址 (imgUrl)、图片类型 (imgType)、图片的宽度 (width) 和高度 (height);
- 在组件的数据中,定义预览图片列表 (previewList) 和预览图片路径 (previewpath)
- 实现两个方法 viewModel() 和 preViewModel() 分别用于仅预览图片和带缩略图预览;
- 在 viewModel() 方法中,通过调用下载文件的 API (downloadFileApi) 并根据返回的文件内容创建 URL 对象,将图片 URL 赋值给 标签的 src 属性;
- 在 preViewModel() 方法中,同样调用下载文件的 API,将返回的文件内容创建 URL 对象,并将 URL 添加到预览图片列表中;
- 使用 watch 监听 imgUrl 属性的变化,在变化时根据 imgType 属性的值来调用对应的方法;
- 在组件的 mounted() 钩子中,根据初始的 imgType 属性值来调用对应的方法;
- 在 main.js 文件中将 tokenImg 组件注册为全局组件,以便在其他地方使用;
- 在需要使用该组件的地方,使用 标签,并传递相应的属性(如图片 URL、图片类型、宽度和高度);
这样,你可以在前端中使用 tokenImg 组件来显示带有 Token 的图片,并支持预览功能。注意确保在组件使用时传递正确的图片 URL、类型、宽度和高度。
封装文件
<template><div><!-- 显示图片 --><img ref="img" :style="{width:width,height:height}" v-if="imgType == 'view'" /><!-- 使用element-ui的el-image进行图片预览 --><el-image :style="{width:width,height:height}" ref="previewimg" v-if="imgType == 'preView'" :src="previewpath":preview-src-list="previewList"></el-image></div>
</template>
<script>
// 引入的接口文件
import { downloadFileApi } from "@/api/publicApi/enumeration";
export default {name: "token-img",props: {// 图片的URL地址imgUrl: {type: String,},// 图片类型,可选为'view'(仅预览图片)或'preView'(可点击预览)imgType: {type: String,default: "view",},// 图片的宽度width: {type: String,},// 图片的高度height: {type: String,},},data() {return {// 预览图片列表previewList: [],// 预览图片路径previewpath: "",};},methods: {// 查看文件 //仅预览图片viewModel() {const img = this.$refs.img;// 调用下载文件的API并根据返回的文件内容创建URL对象downloadFileApi(this.imgUrl).then((res) => {img.src = URL.createObjectURL(res);img.onload = () => {URL.revokeObjectURL(img.src);};});},//带缩略图预览preViewModel() {downloadFileApi(this.imgUrl).then((res) => {// 调用下载文件的API并根据返回的文件内容创建URL对象this.previewpath = URL.createObjectURL(res);this.previewList.push(this.previewpath);});},},watch: {// 监听imgUrl变化imgUrl() {if (this.imgType == "view") {this.viewModel();} else if (this.imgType == "preView") {this.preViewModel();}},},mounted() {if (this.imgType == "view") {this.viewModel();} else if (this.imgType == "preView") {this.preViewModel();}},
};
</script>
引入的接口文件
export function downloadFileApi(imgUrl) {return request({url: "/api/file/examine-preview"+imgUrl,method: "get",responseType: "blob",});
}
main.js
// 将其注册为全局组件
import TokenImg from "@/components/tokenImg";
Vue.component('TokenImg', TokenImg)
使用文件
<TokenImg :width="`50px`" :height="`50px`" :imgUrl="YourUrl" :imgType="`preView`"/>
实现效果
渲染查看
拓展
下载文件携带 token
第一种方式:手写实现
//下载方法
getBgdzByGcsj(row) {// 通过接口下载文件downloadFileApiDown(row.bgdz).then((res) => {// 将文件流转换为下载链接const downloadUrl = URL.createObjectURL(res);// 创建一个<a>标签const link = document.createElement("a");// 设置链接的URL为下载链接link.href = downloadUrl;// 设置下载的文件名为"报表管理.xls"link.download = "报表管理.xls";// 隐藏<a>标签link.style.display = "none";// 将<a>标签添加到页面的<body>中document.body.appendChild(link);// 触发<a>标签的点击事件,开始下载link.click();// 下载完成后删除<a>标签document.body.removeChild(link);});
}