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

使用Flask-RESTful传输图片后无法用ReactJS渲染,求解决方案

解决Flask-RESTful返回图片无法在React中渲染的问题

我来帮你排查下问题核心,其实是axios默认会把响应解析成JSON格式,但Flask返回的是二进制图片数据,这就导致你拿到的res.data是乱码字符串,自然没法直接作为<img>的src属性值。下面是具体的解决方案:

一、React端修改(关键步骤)

你需要修改axios请求的responseType为'blob',让它直接获取图片的二进制Blob对象,再通过URL.createObjectURL转换成可用于图片渲染的临时URL。同时记得在组件卸载时释放这个URL,避免内存泄漏。

修改后的React代码:

class YourComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      image: null,
      features: null // 存储图片的临时URL
    };
    this.imageUrl = null; // 保存URL对象,用于后续释放
  }

  onInputChange = (e) => {
    this.setState({ image: e.target.files[0] });
  };

  onButtonClick = () => {
    const fd = new FormData();
    fd.append('file', this.state.image, this.state.image.name);
    axios.post('http://localhost:5000/image', fd, {
      responseType: 'blob' // 关键:告诉axios返回Blob类型
    }).then(res => {
      // 释放之前的URL(如果存在)
      if (this.imageUrl) {
        URL.revokeObjectURL(this.imageUrl);
      }
      // 创建新的临时URL
      this.imageUrl = URL.createObjectURL(res.data);
      this.setState({ features: this.imageUrl });
    }).catch(err => {
      console.error('上传或获取图片失败:', err);
    });
  };

  componentWillUnmount() {
    // 组件卸载时释放URL,避免内存泄漏
    if (this.imageUrl) {
      URL.revokeObjectURL(this.imageUrl);
    }
  }

  render() {
    const { features } = this.state;
    return (
      <div className="App">
        <input type='file' onChange={this.onInputChange} />
        <button onClick={this.onButtonClick}>Upload</button>
        <br />
        {features && <img src={features} alt='Uploaded preview' />}
      </div>
    );
  }
}

二、Flask端优化(解决跨域问题)

你的React应用大概率运行在localhost:3000,而Flask在localhost:5000,跨域请求会被浏览器拦截,建议添加CORS支持:

  1. 先安装flask-cors依赖:
pip install flask-cors
  1. 修改Flask代码,添加CORS配置:
from flask import Flask, send_file
from flask_restful import Api, Resource, reqparse
import os
import werkzeug
from flask_cors import CORS

app = Flask(__name__)
api = Api(app)
CORS(app) # 允许所有跨域请求,生产环境可配置具体域名

class UploadImage(Resource):
    UPLOAD_FOLDER = 'img'
    parser = reqparse.RequestParser()
    parser.add_argument('file', type=werkzeug.datastructures.FileStorage, location='files', required=True, help='Must provide a file')

    def post(self):
        data = self.parser.parse_args()
        photo = data['file']
        
        if not photo:
            return {'data':'', 'message': 'No File Found', 'status': 'Error'}, 400
        
        # 确保上传目录存在
        if not os.path.exists(self.UPLOAD_FOLDER):
            os.makedirs(self.UPLOAD_FOLDER)
        
        filename = 'input.png'
        path = os.path.join(self.UPLOAD_FOLDER, filename)
        photo.save(path)
        
        return send_file(path, mimetype='image/png')

api.add_resource(UploadImage, '/image')

if __name__ == '__main__':
    app.run(debug=True)

为什么之前的btoa/Blob方法没生效?

因为你之前没有设置responseType: 'blob',axios已经把Flask返回的二进制图片数据自动解析成了JSON格式的乱码字符串,这时候再用btoa处理或者转换成Blob,得到的都是错误的数据,自然无法渲染成图片。只有让axios直接返回Blob对象,才能正确转换成可渲染的图片URL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:34:33