问题:前端发送axios请求,后端响应图片输出流,前端处理显示图片,后端正常返回图片输出流,但是前端却无法显示,不知道是不是我方式错误
我的思路:src中调用函数,函数内部发送请求,然后将图片的响应输出流作为函数的返回值,img的src接收返回值显示图片,代码如下:
请求:
export function getIcon(iconInfo) {
return request({
method: 'post',
url: apiUrl + 'getImage',
data: iconInfo,
responseType: 'blob'
})
}
<div>
<template v-for="item in menuList" :key="item.path">
<!-- 分为两种方式渲染:有子菜单和没有子菜单-->
<el-sub-menu
:index="item.path"
v-if="item.nodeType == 1"
>
<template #title>
<el-icon v-show="item.iconUrl!=null"><img :src="sendIcon(item.iconUrl)" alt="" class="icon_class"/></el-icon>
<span>{{ item.name }}</span>
</template>
<!-- 有子菜单的继续遍历(递归)-->
<menuTree :menuList="item.children"></menuTree>
</el-sub-menu>
<!-- 没有子菜单-->
<el-menu-item :index="item.path" v-if="item.nodeType==2">
<el-icon v-show="item.iconUrl!=null">
<img :src="sendIcon(item.iconUrl)" alt="" class="icon_class"/>
</el-icon>
<span>{{ item.name }}</span>
</el-menu-item>
</template>
</div>
<script>
import {getIcon} from '@/api/home/file/index'
export default ({
name: 'menuTree',
props: ['menuList'],
setup(props) {
function sendIcon(filePath) {
// 获取菜单图片路径
if (filePath != null) {
let FileInfoVo = {
//封装请求参数
filePath: filePath
}
//获取图片输出流
return getIcon(FileInfoVo).then(res => {
return res.data
})
}
}
return {
sendIcon
};
}
})
</script>
其中关键代码如下:
<el-icon v-show="item.iconUrl!=null"><img :src="sendIcon(item.iconUrl)" alt="" class="icon_class"/></el-icon>
<img :src="sendIcon(item.iconUrl)" alt="" class="icon_class"/>
function sendIcon(filePath) {
// 获取菜单图片路径
if (filePath != null) {
let FileInfoVo = {
//封装请求参数
filePath: filePath
}
//获取图片输出流
return getIcon(FileInfoVo).then(res => {
return res.data
})
}
}
后端返回结果正常
但是图片却无法显示
网上说通过Blob来处理
我修改后仍然不能显示图片
检查元素里面却是一个promise对象
奇怪的是我这里输出结果是一个值并非元素里面的是一个promise对象
控制台看下img src
的值是啥
axios接口请求必须添加 responseType:'blob'才能表示是以blob形式接收数据
不知道你这个问题是否已经解决, 如果还没有解决的话:解决方案:
根据你的问题描述,你希望通过后端返回的图片输出流,在Vue前端中显示图片。你的代码中使用了一个sendIcon()
函数来获取图片的输出流,并将其作为<img>
标签的src
属性值。
但是根据你的代码,我发现有以下问题:
sendIcon()
函数中,你调用了后端的接口getIcon()
来获取图片的输出流,但是你直接返回了res.data
,这实际上是一个Promise对象,并不是图片的真实数据。v-show
指令来判断是否显示图片,但是由于sendIcon()
函数返回的是一个Promise对象,并不是一个布尔值,所以这里的判断条件是不正确的。为了解决这个问题,你可以对代码进行如下优化:
sendIcon()
函数中,改为使用async/await
语法来处理异步请求,以便等待获取到图片输出流后再返回。v-if
指令来判断是否显示图片,并在sendIcon()
函数中加入一个isLoading
状态来控制图片的显示与隐藏。下面是优化后的代码示例:
import { getIcon } from '@/api/home/file/index';
export default {
name: 'menuTree',
props: ['menuList'],
setup(props) {
function sendIcon(filePath) {
// 获取菜单图片路径
if (filePath !== null) {
let FileInfoVo = {
//封装请求参数
filePath: filePath
};
let isLoading = true; // 加入一个isLoading状态控制图片的显示与隐藏
(async () => {
try {
// 请求图片输出流
let res = await getIcon(FileInfoVo);
let dataUrl = URL.createObjectURL(res.data); // 将输出流转换成data URL
isLoading = false; // 标记图片加载完成
return dataUrl;
} catch (error) {
console.error('获取图片失败:', error);
isLoading = false; // 标记图片加载完成
return ''; // 返回空字符串表示获取图片失败
}
})();
return isLoading ? null : '';
}
}
return {
sendIcon
};
}
};
修改后的模板:
<el-icon v-show="item.iconUrl != null">
<img v-if="sendIcon(item.iconUrl)" :src="sendIcon(item.iconUrl)" alt="" class="icon_class" />
</el-icon>
这样修改后,应该就能正确地显示图片了。
希望能对你有帮助!如果你还有任何问题,请随时提问。