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

FastAPI+Vuetify多图片下载后无法加载问题求助

问题描述

尝试通过Vuetify前端从FastAPI服务器下载多张图片并展示在卡片组件上,但图片无法加载,显示“Image load failed”错误。文件名属性已成功加载,不清楚图片无法正常加载的原因。


后端FastAPI代码

常量定义

DOWNOAD_PATH = "imgSearch"

下载函数

def download(file_path):
    if os.path.isfile(file_path):
        return FileResponse(path=file_path, media_type="image/jpg", filename=os.path.basename(file_path))
    return None

接口路由

@router.get('/img/download')
async def download_images():
    lsImages = []
    i = 0
    for imgFilename in os.listdir(DOWNOAD_PATH):
        lsImages.append(download(os.path.join(DOWNOAD_PATH, imgFilename)))
        print("Image: " + imgFilename) ; i = i + 1
    if lsImages: return lsImages
    return {"error" : "File not found!"}

前端Vuetify代码

卡片组件模板

<v-card>
    <v-subheader>Output Images</v-subheader>
    <v-container fluid  grid-list-md >
        <v-layout row wrap>
            <v-flex
                v-for="card0 in cards"
                :key="card0.title"
                v-bind="{ [`xs${card0.flex}`]: true }"
            >
                <v-card elevation="10">
                    <v-img
                        :src="card0.src"
                        height="175px" 
                    >                  
                    </v-img>
                    <v-card-title class="text-h6" v-text="card0.title"></v-card-title>
                </v-card>
            </v-flex>
        </v-layout>
    </v-container>
</v-card>

请求处理方法

onUploadSelectedFileClick () {  
    axios({
        method: 'get',
        url: `${apiUrl}/api/v1/img/download`,
        responseType: 'stream' 
    })
    .then(response => {
        const imgSearches = response.data;
        let i = 0 
        var jInput = this.iInput * 4;
        for (const file of imgSearches) {
            if (jInput > i) { 
                Vue.set(this.cards, i, {title: file.filename, src: file.path, flex: 3 });  
                i++
            }
        };
    })
    .catch(error => {
        console.error(error);
    });      
}

问题原因分析

  1. 后端返回格式无效:download_images接口返回FileResponse对象列表,FastAPI无法将多个FileResponse序列化为前端可解析的JSON。前端拿到的file.path是服务器本地路径,浏览器无法直接访问服务器本地文件系统。
  2. 前端请求类型错误:设置responseType: 'stream'不符合需求,实际需要的是可解析的JSON数据而非流格式。

解决方案

方案一:返回图片访问URL(推荐)

通过FastAPI挂载静态文件目录,让前端直接通过URL加载图片。

后端修改

from fastapi.staticfiles import StaticFiles

# 挂载图片目录为静态资源,前端可通过/static/文件名访问
app.mount("/static", StaticFiles(directory=DOWNOAD_PATH), name="static")

@router.get('/img/download')
async def download_images():
    lsImages = []
    for imgFilename in os.listdir(DOWNOAD_PATH):
        file_path = os.path.join(DOWNOAD_PATH, imgFilename)
        if os.path.isfile(file_path):
            # 生成前端可访问的图片URL
            img_url = f"/static/{imgFilename}"
            lsImages.append({"filename": imgFilename, "url": img_url})
    return lsImages if lsImages else {"error": "File not found!"}

前端修改请求方法

onUploadSelectedFileClick () {  
    axios.get(`${apiUrl}/api/v1/img/download`)
    .then(response => {
        const imgSearches = response.data;
        let i = 0 
        const jInput = this.iInput * 4;
        for (const file of imgSearches) {
            if (jInput > i) { 
                Vue.set(this.cards, i, {title: file.filename, src: file.url, flex: 3 });  
                i++
            }
        };
    })
    .catch(error => {
        console.error(error);
    });      
}

方案二:返回Base64编码图片

将图片转为Base64字符串返回,前端直接用该字符串作为图片源。

后端修改

import base64

def image_to_base64(file_path):
    with open(file_path, "rb") as f:
        return base64.b64encode(f.read()).decode('utf-8')

@router.get('/img/download')
async def download_images():
    lsImages = []
    for imgFilename in os.listdir(DOWNOAD_PATH):
        file_path = os.path.join(DOWNOAD_PATH, imgFilename)
        if os.path.isfile(file_path):
            base64_str = image_to_base64(file_path)
            img_src = f"data:image/jpg;base64,{base64_str}"
            lsImages.append({"filename": imgFilename, "src": img_src})
    return lsImages if lsImages else {"error": "File not found!"}

前端修改请求方法

onUploadSelectedFileClick () {  
    axios.get(`${apiUrl}/api/v1/img/download`)
    .then(response => {
        const imgSearches = response.data;
        let i = 0 
        const jInput = this.iInput * 4;
        for (const file of imgSearches) {
            if (jInput > i) { 
                Vue.set(this.cards, i, {title: file.filename, src: file.src, flex: 3 });  
                i++
            }
        };
    })
    .catch(error => {
        console.error(error);
    });      
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 15:05:30