img标签请求浏览器资源携带请求头

1.问题背景

项目中图片上传的功能,需要在el-table中展示,并且点击编辑需要在el-upload中重新展示上传的图片; 图片并不是保存在数据库中,而是保存在miniIO中(miniIO是一个文件存储服务器,文件上传后存储在根据日期划分的文件夹中,比如/20250331/abc123_fhgjiouyyAdf-ffeegkki.jpg),文件上传成功后,接口返回的是类似这样的数据

js 复制代码
{
 code:'0000',
 data:{
     fileName:'1.jpg',
     url:'/20250331/abc123_fhgjiouyyAdf-ffeegkki.jpg'
 }
}

意思就是接口只返回文件在miniIO中地址; 现在图片上传成功在表格中创建一条数据后,在表格中无法展示,并且点击编辑,el-upload组件汇总无法回显图片;

2.原因分析

(1)表格中无法展示图片 表格中使用el-image标签展示图片

html 复制代码
<template slot-scope="scope">
    <el-image :src="scope.row.url" style="width:50px;height:50px;" fit="contain"/>
</template>

在js代码中打印url的格式是

js 复制代码
http://localhost/data/jjjj/20250331/abc123_fhgjiouyyAdf-ffeegkki.jpg

明显请求的路径地址不对,本地调试的时候需要代理到服务器地址 (2)图片请求需要携带headers 由于后端表格数据返回的只是图片在miniIO上的文件地址,而不是一个blob类型的数据,所以想要获取图片,其实还需要再次请求后端的地址来获取blob类型的数据; el-image的底层使用的还是img标签,当img标签的src属性中是一个图片地址的时候(网络地址),它会通过浏览器向这个网络地址发起一个请求,请求图片的资源; 但是后端为了安全,对每个请求做了限制,需要在headers中携带Authorization,但是img标签请求图片资源是浏览器控制的,它不会经过axios,所以在axios的请求拦截器中添加的headers操作不会实现在img请求中; (3)el-upload无法复现图片 el-upload组件有一个属性header,但是它只能在发起上传图片请求的时候携带在请求中,复现图片主要依靠的是将file放入file-list中,这样可以在el-ipload中展示图片; el-upload底层也是使用的img标签,这样和上一个原因一样,也是因为再次请求图片资源的时候没有携带Authorization导致图片资源没有下载下来导致无法展示;

3.解决办法

(1)后端修改对图片资源请求接口的限制

可以做,但是不能做,原因都懂的

(2)使用serviceWorker来代理img请求

有限制:serviceWorker只能在 http://localhost 和 https:// 中使用,这意味着当你的项目线上环境的访问ip是http开头的时候,这种方式就不能使用; 1)新建serviceWorker文件:public/sw.js

js 复制代码
// sw.js
let authToken = null;

self.addEventListener('message', (event) => {
  if (event.data.type === 'SET_TOKEN' || event.data.type === 'UPDATE_TOKEN') {
    authToken = event.data.token;
  }
});

self.addEventListener('fetch', (event) => {
  if (authToken && event.request.url.endsWith('.jpg')) {
    const newHeaders = new Headers(event.request.headers);
    newHeaders.set('Authorization', `Bearer ${authToken}`);
    
    event.respondWith(
      fetch(new Request(event.request, { headers: newHeaders }))
    );
  }
});

2)在msin.js中注册serviceWorker并且传递token

javascript 复制代码
if ('serviceWorker' in navigator) {
  // 注册时传递 Token
  navigator.serviceWorker.register('/sw.js').then(registration => {
    // 从存储中获取 Token
    const token = localStorage.getItem('auth_token') || 
                  getCookie('auth_token');
    
    // 发送给 Service Worker
    registration.active?.postMessage({ 
      type: 'SET_TOKEN', 
      token 
    });
  });

  // 监听存储变化实时更新
  window.addEventListener('storage', () => {
    navigator.serviceWorker.controller?.postMessage({
      type: 'UPDATE_TOKEN',
      token: localStorage.getItem('auth_token')
    });
  });
}

(3)笨办法:在url放入img标签前重新请求图片资源

1)在el-table中,获取到表格数据后,取出每条数据中的url字段,使用axios、fetch、XMLHttpRequest进行请求,封装一个requestImgUrl方法

js 复制代码
async function requestImgUrl(url){
    const response  =await axios.get(
        url:url,
        {
            responseType:'blob',
            headers:{
                Authorization:"bearer"+getToken(),//getToken是封装的获取Cookies或者sessionStorage中存储的token的方法
            }
        }
    )
    return URL.createObjectURL(response.data)
}

在获取表格数据时进行遍历

js 复制代码
for(let item of res.data)
    item.url = await requestImgUrl(item.url)
}

2)el-upload中也是同样的方法,这是需要放入file-list中

html 复制代码
<el-upload
...
:file-list="fileList"
...
/>
js 复制代码
async function editData(row){
    ...
    if(row.url){
        let blobData = await requestImgUrl(row.url)
        fileList.vlaue = [{
            url:blobData
        }]
    }
    ...
}
相关推荐
qq. 28040339845 小时前
CSS层叠顺序
前端·css
喝拿铁写前端5 小时前
SmartField AI:让每个字段都找到归属!
前端·算法
猫猫不是喵喵.5 小时前
vue 路由
前端·javascript·vue.js
烛阴6 小时前
JavaScript Import/Export:告别混乱,拥抱模块化!
前端·javascript
bin91536 小时前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例12,TableView16_12 拖拽动画示例
前端·javascript·vue.js·ecmascript·deepseek
GISer_Jing6 小时前
[Html]overflow: auto 失效原因,flex 1却未设置min-height &overflow的几个属性以及应用场景
前端·html
程序员黄同学6 小时前
解释 Webpack 中的模块打包机制,如何配置 Webpack 进行项目构建?
前端·webpack·node.js
拉不动的猪6 小时前
vue自定义“权限控制”指令
前端·javascript·vue.js
再学一点就睡6 小时前
浏览器页面渲染机制深度解析:从构建 DOM 到 transform 高效渲染的底层逻辑
前端·css
拉不动的猪7 小时前
刷刷题48 (setState常规问答)
前端·react.js·面试