使用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支持:
- 先安装flask-cors依赖:
pip install flask-cors
- 修改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
相关产品推荐
相关产品推荐

