React使用express-fileupload时如何获取其他表单文本输入字段
React 结合 express-fileupload 上传文件时同时获取普通表单字段的实现方案
问题根因
当前的请求写法存在两个关键错误,直接导致普通表单字段无法被后端解析:
- axios.post 的参数规则是
axios.post(url, 请求体载荷, 配置项),现在代码把携带文件的 FormData 当请求体,把monitor/contactos/excepciones三个普通表单字段塞到了第三个参数(axios 配置项)的位置,这部分内容根本不会被发送到后端,自然req.body里找不到对应字段。 - 带文件上传的
multipart/form-data格式请求不能直接传递JSON对象,所有非文件的普通字段必须全部追加到同一个 FormData 实例里,后端才能正确解析到对应值。
当不携带文件、直接把
{monitor, contactos, excepciones}当JSON发请求时,express.json()中间件会正常解析JSON请求体,所以req.body能拿到完整字段,req.files自然是 undefined。
当只把文件塞进 FormData 发请求时,express-fileupload中间件能正常解析 multipart 格式的请求拿到文件,但因为根本没把其他普通字段发到请求里,req.body只有空对象,所以读取req.body.monitor时直接抛出 undefined 的属性读取错误。
前端正确实现
1. 统一收集所有字段到同一个 FormData 实例
嵌套对象、数组类型的字段不能直接 append,需要先做 JSON 字符串序列化,避免后端解析成纯字符串拿不到结构:
// 初始化FormData const formData = new FormData(); // 追加文件字段 if (archivoSFTP) { formData.append('directorioFTP', archivoSFTP); } // 追加普通嵌套对象、数组字段,必须先转成JSON字符串 formData.append('monitor', JSON.stringify(monitor)); formData.append('contactos', JSON.stringify(contactos)); formData.append('exepciones', JSON.stringify(excepciones));
2. 正确发送axios请求
不需要手动设置 Content-Type,浏览器会自动根据 FormData 的内容设置正确的 multipart/form-data 边界值,手动设置反而会导致解析失败:
const response = await axios.post( 'http://localhost:4000/api/monitor', formData // 所有请求载荷都放在第二个参数位置 // 第三个参数是axios配置项,不要在这里塞业务字段 );
后端调整点
因为发给后端的嵌套对象、数组是 JSON 字符串格式,需要在路由处理时先把对应的字符串字段解析成原生对象,否则拿不到嵌套属性:
controladorMonitor.crear = async (req, res) => { // 先解析从FormData传来的JSON字符串字段 const monitor = JSON.parse(req.body.monitor); const contactos = JSON.parse(req.body.contactos); const exepciones = JSON.parse(req.body.exepciones); // 打印验证,此时req.files能拿到上传的文件,req.body能拿到所有字符串字段 console.log('上传文件:', req.files); console.log('普通字段:', req.body); const crearMonitor = new Monitor({ generales: { urlSitio: monitor.urlSitio, userAgent: monitor.userAgent, cookieName: monitor.cookieName, validaURL: monitor.validaURL, monitoreaCada: monitor.monitoreaCada, generarMinitatura: monitor.generarMinitatura }, maximoAlertas: monitor.maximoAlertas, contactos: contactos, exepcionesTexto: exepciones, habilitarExepcionesTexto: monitor.habilitarExepcionesTexto, antiDefaced: monitor.antiDefaced, integridadImagen: monitor.integridadImagen, porcentajeIgualdad: monitor.porcentajeIgualdad, porcentajeIgual: monitor.porcentajeIgual, fuzzyHashing: monitor.fuzzyHashing, fuzzyHash: monitor.fuzzyHash, igualdad: monitor.igualdad, ftp: monitor.ipFTP, usuarioFTP: monitor.usuarioFTP, contraseniaFTP: monitor.contraseniaFTP, directorioFTP: monitor.directorioFTP, puertoFTP: monitor.puertoFTP, ipSSH: monitor.ipSSH, usuarioSSH: monitor.usuarioSSH, contraseniaSSH: monitor.contraseniaSSH, directorioSSH: monitor.directorioSSH, puertoSSH: monitor.puertoSSH }) try { await crearMonitor.save(); if (!fse.existsSync(crearMonitor._id)) { fse.mkdirSync('archivos/'+crearMonitor._id) } res.status(201).json('Monitor creado exitosamente'); } catch (err) { generateLog('db_error', err); res.status(400).json('Error en la petición') } };
额外注意事项
- 不要把 FormData 实例和普通JSON对象混在同一个请求体中发送,axios 会自动将传入 FormData 的请求识别为 multipart/form-data 格式,其他塞在请求体里的普通对象不会被正确序列化传递,最终后端会拿到空的请求体。
- 不要手动给 axios 设置
Content-Type: multipart/form-data,浏览器会自动生成带 boundary 分隔标识的请求头,手动配置会导致后端中间件无法正确分割请求体,出现 req.body、req.files 全为空的异常。 - 当前后端服务的中间件顺序是符合要求的:cors、日志、JSON解析、urlencoded解析、文件上传、静态服务,这个顺序不需要调整,express-fileupload 会自动处理 multipart 格式的请求,把文件挂载到 req.files、普通文本字段挂载到 req.body。
内容的提问来源于stack exchange,提问作者berry_malicious
相关产品推荐
相关产品推荐

