如何用React.js(Next.js)和PHP实现FormData的上传与接收?
解决React(Next.js)通过Axios发送FormData到PHP无法接收参数的问题
核心问题分析
React端问题:
- 变量名写错:代码里用
data.append('avatar', file),但创建的FormData变量是formData,应该改成formData.append('avatar', file)。 - 手动设置请求头错误:发送FormData时,Axios会自动生成带
boundary的multipart/form-data请求头,手动设置会丢失boundary,导致PHP无法解析表单数据。 - 未阻止表单默认行为:表单提交会触发页面刷新,必须在
handleSubmit里加e.preventDefault();。 - 文件状态缺失:
handleFileSelect需要把选中的文件存到状态里,确保file变量有值。
PHP端问题:
multipart/form-data格式的请求,PHP会自动把文本参数解析到$_POST数组,上传文件解析到$_FILES数组,不需要用file_get_contents("php://input")读取原始数据(读出来的是字符串,不能直接当数组用)。
修正后的完整代码
React(Next.js)提交代码
import { useState } from 'react'; import axios from 'axios'; const YourComponent = () => { const [state, setState] = useState({ name: '' }); const [file, setFile] = useState<File | null>(null); // 处理文件选择 const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => { if (e.target.files?.[0]) { setFile(e.target.files[0]); } }; // 处理输入框内容变化 const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { setState(prev => ({ ...prev, name: e.target.value })); }; const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { // 阻止表单默认刷新行为 e.preventDefault(); if (!file) { alert('请选择文件'); return; } const formData = new FormData(); // 添加文本参数,可使用输入框值或测试静态值 formData.append("title", state.name || "test"); // 添加上传文件 formData.append('avatar', file); try { const response = await axios.post( "https://xxxxxxxxxxxxxxxxxxxxxxxxxx/", formData // 无需手动设置Content-Type,Axios会自动处理 ); alert('响应:' + response.data.msg); console.log("请求成功", response.data); } catch (error) { alert('请求失败:' + (error as Error).message); console.log("请求失败", error); } }; return ( <form className="forms-sample" onSubmit={handleSubmit}> <input type="file" onChange={handleFileSelect} /> <input type="text" className="form-control" id="exampleInputName1" placeholder="Title" name="name" value={state.name} onChange={handleChange} /> <button type="submit">提交</button> </form> ); }; export default YourComponent;
PHP接收代码
public function test3() { // 获取文本参数,用??处理参数不存在的情况 $title = $_POST['title'] ?? '无标题'; // 获取上传文件信息 $avatar = $_FILES['avatar'] ?? null; // 输出测试文本参数 echo "title is " . $title; // 处理文件上传逻辑 if ($avatar && $avatar['error'] === UPLOAD_ERR_OK) { $uploadDir = './uploads/'; // 确保上传目录存在,不存在则创建 if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } // 生成唯一文件名避免重复 $fileName = uniqid() . '_' . basename($avatar['name']); $uploadPath = $uploadDir . $fileName; // 移动临时文件到目标目录 if (move_uploaded_file($avatar['tmp_name'], $uploadPath)) { echo "<br>文件上传成功,路径:" . $uploadPath; } else { echo "<br>文件上传失败"; } } }
额外注意事项
- 确保PHP配置里的
upload_max_filesize和post_max_size值足够大,避免大文件上传被拦截。 - 如果是跨域请求,PHP端需要配置CORS,允许对应的请求来源、方法和请求头。
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

