后端响应图片输出流,vue无法显示图片

问题:前端发送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
        })
      }
    }

后端返回结果正常

img

但是图片却无法显示

img

网上说通过Blob来处理

img

我修改后仍然不能显示图片

img

检查元素里面却是一个promise对象

img

奇怪的是我这里输出结果是一个值并非元素里面的是一个promise对象

img

img

控制台看下img src的值是啥

axios接口请求必须添加 responseType:'blob'才能表示是以blob形式接收数据

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答由chatgpt基于相关博客总结生成:

    解决方案:

    根据你的问题描述,你希望通过后端返回的图片输出流,在Vue前端中显示图片。你的代码中使用了一个sendIcon()函数来获取图片的输出流,并将其作为<img>标签的src属性值。

    但是根据你的代码,我发现有以下问题:

    1. sendIcon()函数中,你调用了后端的接口getIcon()来获取图片的输出流,但是你直接返回了res.data,这实际上是一个Promise对象,并不是图片的真实数据。
    2. 你在模板中使用了v-show指令来判断是否显示图片,但是由于sendIcon()函数返回的是一个Promise对象,并不是一个布尔值,所以这里的判断条件是不正确的。

    为了解决这个问题,你可以对代码进行如下优化:

    1. sendIcon()函数中,改为使用async/await语法来处理异步请求,以便等待获取到图片输出流后再返回。
    2. 在模板中使用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>
    

    这样修改后,应该就能正确地显示图片了。

    希望能对你有帮助!如果你还有任何问题,请随时提问。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^