如何在 React 中显示 FastAPI 的 Fileresponse 图像?

the*_*edi 4 javascript jsx typescript reactjs fastapi

这是我的前端 React 代码:

import * as React from 'react';
import { useEffect, useState } from 'react';

import http from './http-common'; // axios

type Photo = {
  filename: string,
  caption: string,
  tags: string[].
};

const BrowserArticle = ({ filename, caption, tags }: Photo) => {
  const [photoFile, setFile] = useState<string>('');

  useEffect(() => {
    http.get(`/api/getImg/${filename}`)
      .then((response) => {
        console.log(typeof response.data); // console output is 'string'
        console.log(response); // see screenshot below
        setFile(data);
      });
  }, []);

  return (
    <div>
      <img src={photoFile} alt={filename} />
      <div>{caption}</div>
      <div>
        {
           tags.map((tag) => tag)
        }
      </div>
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)

这是我的后端 FastAPI 代码:

from fastapi import FastAPI
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles

app = FastAPI()
app.mount('/static', StaticFiles(directory='static'), name='static')

@app.get('/api/getImg/{image_filename}')
async def get_image(image_filename: str) -> FileResponse:
  return FileResponse(f'./static/uploads/{image_filename}')
Run Code Online (Sandbox Code Playgroud)

CORS 已得到解决。当我向服务器发送请求时,已成功收到响应,但图像无法加载。经检查,这是生成的 HTML:

在此输入图像描述

当我console.log(data)进入该then()函数时,这就是我得到的:

在此输入图像描述

当我使用 FastAPI 的内置工具测试 API 时,我验证了 AP​​I 成功返回blob:http://192.168.1.201:8000/0a870a00-cf63-43ef-b952-e49770137fdd

我怀疑 axios 接收到的数据是图像文件本身,所以我尝试按如下方式更改代码:

const [photoFile, setFile] = useState<File | null>(null);

// ...

<img src={photoFile === null ? '' : URL.createObjectURL(photoFile)} alt={filename} />
Run Code Online (Sandbox Code Playgroud)

但是当我刷新页面时,我得到了TypeError: Failed to execute 'createObjectURL' on 'URL': Overload resolution failed.

我尝试搜索如何正确显示从后端接收的图像,但我发现的唯一结果讨论了如何将图像发送到后端或如何显示正在上传到服务器的图像(即显示选择通过 上传的文件的缩略图。<input type="file" />没有关于这个特殊问题,有什么想法吗?

更新:当我执行以下操作时,图像成功显示:

<img src={`http://192.168.1.201:8000/api/getImg/${filename}`} alt={filename} />
Run Code Online (Sandbox Code Playgroud)

但这意味着在生成的 HTML 中公开我的后端,并对后端 IP 进行硬编码。有没有更“正确”的方法来做到这一点?

小智 5

我想出的方法是在 FastAPI 中将图像编码为 Base64,通过 API 调用将 Base64 编码图像发送到前端,并在 React 中以 Base64 编码格式渲染图像。这是它的一些代码。
FastAPI代码(记住不要使用response_model=FileResponse

with open(imgpath, 'rb') as f:
    base64image = base64.b64encode(f.read())
return base64image
Run Code Online (Sandbox Code Playgroud)

反应代码。

<img src={data:image/jpeg;base64,${data}} />
Run Code Online (Sandbox Code Playgroud)

这里,${data}是base64编码的图像。