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

如何在发送前修改FormData?实现图片转Base64并在子组件复用

解决方案:表单提交前修改FormData并将图片转为Base64

原代码核心问题

  1. 文件输入框name属性错误设置为title,导致FormData中无法获取到file字段
  2. 仅在文件选择时转换Base64,但未将编码值存入提交的FormData,默认表单提交仍会使用原始文件(或因name错误导致字段缺失)
  3. React Router的Form组件默认自动提交,无法拦截并修改FormData

一、修改AddForm组件:自定义表单提交逻辑

通过拦截表单提交事件,手动构造并修改FormData,同时存储Base64编码的图片数据:

import { Form, useNavigation } from 'react-router-dom';
import { useState } from 'react';
import classes from './AuthForm.module.css';

function AddForm() {
  const navigation = useNavigation();
  const isSubmitting = navigation.state === 'submitting';
  const [base64Image, setBase64Image] = useState('');

  // 图片转Base64工具函数
  function fileToBase64(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result);
      reader.onerror = (error) => reject(error);
    });
  }

  // 处理文件选择,转换并存储Base64
  async function handleFileInputChange(event) {
    const file = event.target.files[0];
    if (!file) return;
    
    try {
      const base64 = await fileToBase64(file);
      setBase64Image(base64);
    } catch (error) {
      console.error('图片转Base64失败:', error);
    }
  }

  // 拦截表单提交,修改FormData后手动发送
  async function handleSubmit(event) {
    event.preventDefault();
    const formElement = event.target;
    const formData = new FormData(formElement);

    // 替换原始文件为Base64编码值
    if (base64Image) {
      formData.delete('file');
      formData.append('file', base64Image);
    }

    // 使用fetch发送自定义FormData
    await fetch(formElement.action, {
      method: formElement.method,
      body: formData,
    });

    // 提交后重置表单和状态
    formElement.reset();
    setBase64Image('');
  }

  return (
    <>
      <Form method="post" className={classes.form} onSubmit={handleSubmit}>
        <div>
          <label htmlFor="title">Tytuł:</label>
          <input
            type="text"
            id="title"
            name='title'
            required
          />
        </div>
        <div>
          <label htmlFor="file">Wybierz plik:</label>
          <input
            type="file"
            id="file"
            name='file'  {/* 修正name属性为file */}
            onChange={handleFileInputChange}
            accept="image/*"  {/* 可选:限制仅上传图片 */}
          />
        </div>
        <button disabled={isSubmitting}>
          {isSubmitting ? 'Adding...' : 'Add'}
        </button>
      </Form>
    </>
  );
}

export default AddForm;

二、修正AddPage的action函数

修正拼写错误,并确保能正确获取Base64数据:

import AddForm from '../components/AddForm';

function AddPage() {
  return <AddForm/>; 
}

export default AddPage;

export async function action({ request }) { 
  const data = await request.formData();
  console.log('FormData内容:', data);
  
  const postData = { 
    title: data.get('title'),  // 修正拼写错误:titlt -> title
    file: data.get('file'),    // 现在可获取到Base64编码的图片
  };
  
  console.log('处理后的提交数据:', postData);
  
  // 此处可添加发送到后端的逻辑,例如:
  // await fetch('/api/posts', {
  //   method: 'POST',
  //   headers: { 'Content-Type': 'application/json' },
  //   body: JSON.stringify(postData)
  // });
  
  return null;
}

关键说明

  • 修改FormData时机:在handleSubmit中阻止默认提交,手动构造FormData并修改字段,确保提交的是自定义后的数据
  • Base64传递:通过useState存储编码后的图片,提交时替换FormData中的原始文件字段
  • 字段一致性:文件输入框的name属性必须与action中获取数据的key(file)保持一致,否则会出现字段为null的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 10:37:15