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

如何在不使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:45:42