You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3无法渲染Django REST API返回的图片问题求助

问题根源

核心问题是Axios默认以JSON格式处理响应,但图片是二进制数据,你直接把整个Axios响应对象赋值给image,img标签的src无法识别这个对象,所以显示灰色占位框。另外模板里的this.image写法也不符合Vue模板规范,模板中不需要加this。


前端(Vue 3)修复方案

修改getImage方法,让Axios正确处理二进制图片数据,再转换成浏览器能识别的URL格式:

<script setup>
</script>

<script>
import axios from "axios";

export default {
  name: "SongBox",
  props: ['song'],
  methods: {
    async getImage() {
      try {
        // 关键配置:告诉Axios处理二进制blob数据
        const response = await axios.get(this.$hostname + 'img?id=' + this.song.pk, {
          responseType: 'blob'
        });
        // 将Blob转换成可直接用于src的Object URL
        this.image = URL.createObjectURL(response.data);
      } catch (error) {
        // 请求失败时设置默认占位图(可替换成你的默认图路径/base64)
        this.image = '';
      }
    }
  },
  created() {
    this.getImage()
  },
  beforeUnmount() {
    // 组件销毁时释放Object URL,避免内存泄漏
    if (this.image) {
      URL.revokeObjectURL(this.image);
    }
  },
  data() {
    return {
      image: '' // 初始化为空字符串,避免无效src导致占位
    }
  }
}
</script>

<template>
  <div v-if="song" class="flex w-1/3 flex-wrap px-3 -mb-12">
    <div class="w-full px-2">
      <div class="relative overflow-hidden bg-cover bg-no-repeat" style="background-position: 50%">
        <!-- 去掉this,直接使用image变量 -->
        <img class="block w-full h-full rounded-lg object-cover object-center" :src="image" alt="专辑封面"/>
        <div class="absolute rounded-lg bottom-0 right-0 left-0 top-0 h-full w-full bg-black bg-fixed opacity-50 overflow-hidden"></div>
      </div>
      <div class="relative inset-y-[-20%] bottom-5 hidden py-5 text-center text-white md:block">
        <p class="text-xl">{{ song.fields.song_name }}</p>
        <p class="text-base">{{ song.fields.song_artist }}</p>
      </div>
    </div>
  </div>
</template>

后端(Django REST)优化建议

你的后端代码存在冗余和潜在报错风险(比如直接取request.GET['id']会触发KeyError),可以优化为更健壮的版本:

from django.http import FileResponse, HttpResponseNotFound
from rest_framework.decorators import api_view
from .models import Song
import os

@api_view(['GET'])
def img_api(request):
    song_id = request.GET.get('id')
    # 处理id为空或undefined的情况
    if not song_id or song_id == 'undefined':
        return HttpResponseNotFound(content_type='application/json')
    
    song = Song.objects.filter(song_id=song_id).first()
    if not song:
        return HttpResponseNotFound(content_type='application/json')
    
    img_path = os.path.join(SONG_PATH, song.song_image_file)
    try:
        # 根据后缀返回对应Content-Type
        if song.song_image_file.endswith(".png"):
            return FileResponse(open(img_path, 'rb'), content_type='image/png')
        else:
            return FileResponse(open(img_path, 'rb'), content_type='image/jpeg')
    except (FileNotFoundError, PermissionError):
        return HttpResponseNotFound(content_type='application/json')

额外提示

  • 可以给img标签加v-if="image",或者用骨架屏占位,避免初始阶段显示灰色框。
  • 务必在组件销毁时调用URL.revokeObjectURL释放资源,防止内存泄漏。

内容的提问来源于stack exchange,提问作者thenordwrath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 05:23:19