如何在不使用FormData时,高效将ReactJS Antd上传组件的Base64图片发至Python服务器
前端(React + Antd)实现
核心思路
通过Antd Upload的customRequest完全接管上传逻辑,将图片文件转成Base64(可选压缩优化)后,以JSON格式发送至后端,全程不使用FormData。
1. Upload组件基础配置
import { Upload, Button, message } from 'antd'; import { UploadOutlined } from '@ant-design/icons'; import axios from 'axios'; const ImageUpload = () => { // 自定义上传逻辑 const customUpload = async ({ file, onSuccess, onError }) => { try { // 转Base64并压缩 const base64Str = await convertFileToBase64(file, { quality: 0.8 }); // 发送JSON请求 const res = await axios.post('/api/upload-image', { image: base64Str, filename: file.name }); onSuccess(res.data); message.success('上传成功'); } catch (err) { onError(err); message.error('上传失败'); } }; return ( <Upload customRequest={customUpload} showUploadList={false} accept="image/*" > <Button icon={<UploadOutlined />}>选择图片上传</Button> </Upload> ); }; export default ImageUpload;
2. 图片转Base64(含压缩优化)
通过Canvas压缩图片体积,减少Base64传输量,提升效率:
const convertFileToBase64 = (file, options = { quality: 0.9 }) => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => { const img = new Image(); img.src = e.target.result; img.onload = () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // 按比例缩小大尺寸图片 const maxWidth = 1920; const maxHeight = 1080; let width = img.width; let height = img.height; if (width > maxWidth) { height = (height * maxWidth) / width; width = maxWidth; } if (height > maxHeight) { width = (width * maxHeight) / height; height = maxHeight; } canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); // 移除Base64前缀,减少传输数据 const base64 = canvas.toDataURL(file.type, options.quality).replace(/^data:image\/\w+;base64,/, ''); resolve(base64); }; img.onerror = reject; }; reader.onerror = reject; reader.readAsDataURL(file); }); };
后端(Python)实现
Flask版本
from flask import Flask, request, jsonify import base64 import os from datetime import datetime app = Flask(__name__) # 确保上传目录存在 UPLOAD_DIR = 'uploaded_images' os.makedirs(UPLOAD_DIR, exist_ok=True) @app.route('/api/upload-image', methods=['POST']) def upload_image(): try: req_data = request.get_json() base64_str = req_data.get('image') filename = req_data.get('filename', f"img_{datetime.now().strftime('%Y%m%d%H%M%S')}.png") # 解码Base64并保存 image_bytes = base64.b64decode(base64_str) save_path = os.path.join(UPLOAD_DIR, filename) with open(save_path, 'wb') as f: f.write(image_bytes) return jsonify({ 'status': 'success', 'save_path': save_path }), 200 except Exception as e: return jsonify({ 'status': 'error', 'msg': str(e) }), 500 if __name__ == '__main__': app.run(debug=True)
FastAPI版本(可选)
from fastapi import FastAPI, Request from fastapi.responses import JSONResponse import base64 import os from datetime import datetime app = FastAPI() UPLOAD_DIR = 'uploaded_images' os.makedirs(UPLOAD_DIR, exist_ok=True) @app.post('/api/upload-image') async def upload_image(request: Request): try: req_data = await request.json() base64_str = req_data.get('image') filename = req_data.get('filename', f"img_{datetime.now().strftime('%Y%m%d%H%M%S')}.png") image_bytes = base64.b64decode(base64_str) save_path = os.path.join(UPLOAD_DIR, filename) with open(save_path, 'wb') as f: f.write(image_bytes) return JSONResponse(content={ 'status': 'success', 'save_path': save_path }, status_code=200) except Exception as e: return JSONResponse(content={ 'status': 'error', 'msg': str(e) }, status_code=500)
关键注意事项
- Base64体积优化:Base64编码会比原文件大30%左右,前端压缩是必要步骤,否则大图片传输效率极低。
- 请求头兼容:前端axios默认会设置
Content-Type: application/json,后端需确保能正确解析JSON请求体。 - 异常处理:前端要捕获文件读取、压缩、请求的错误;后端要处理Base64解码失败、文件写入失败等异常场景。
内容的提问来源于stack exchange,提问作者manimk
相关产品推荐
相关产品推荐

