如何从React向Node.js发送同时包含文件与JSON数据的单次请求
实现方案:单次请求同时上传文本数据与图片文件到Express服务
前端实现逻辑
- 使用浏览器原生的
FormData接口封装所有数据,该接口天然支持同时承载二进制文件和文本键值对,会自动设置multipart/form-data编码类型,无需手动修改请求头 - 具体操作步骤:
- 获取用户输入的文本数据(商品名、分类、描述、价格)和选中的图片文件对象后,实例化空的
FormData对象 - 调用
append()方法按后端约定的键名,依次添加所有文本字段,价格类的数字可以直接传入,后端接收后再做类型转换即可 - 调用
append()方法添加图片文件对象,多张图片可以用同一个键名加数组后缀(比如productImages[])或者按序号命名实现批量上传 - 用
fetch、axios等请求库把FormData实例作为请求体直接发送,不需要额外序列化处理
前端示例代码:
- 获取用户输入的文本数据(商品名、分类、描述、价格)和选中的图片文件对象后,实例化空的
// 假设已获取表单输入和文件对象 const productName = document.querySelector('#product-name').value const category = document.querySelector('#category').value const description = document.querySelector('#description').value const price = document.querySelector('#price').value const productImage = document.querySelector('#image-upload').files[0] // 封装FormData const formData = new FormData() formData.append('name', productName) formData.append('category', category) formData.append('description', description) formData.append('price', price) formData.append('productImage', productImage) // 发送请求 fetch('/api/product/create', { method: 'POST', body: formData }) .then(res => res.json()) .then(data => console.log('提交成功', data))
后端Express处理逻辑
- Express原生不支持解析
multipart/form-data类型的请求体,需要引入multer中间件处理文件上传,这是目前Express生态最成熟的文件处理中间件 - 具体操作步骤:
- 安装依赖:
npm install multer pg - 配置
multer:支持两种存储模式,一是将图片存储到本地磁盘/对象存储服务,数据库仅存访问路径;二是直接拿到文件二进制Buffer存入PostgreSQL,更推荐前者,避免数据库体积过大影响查询性能 - 在对应接口路由上挂载
multer中间件,配置接收的文件字段名、数量、大小限制 - 接口处理函数中通过
req.body获取所有文本字段,通过req.file(单文件)/req.files(多文件)获取上传的文件信息 - 将文本数据和文件的存储路径/二进制数据写入PostgreSQL即可
后端示例代码:
- 安装依赖:
const express = require('express') const multer = require('multer') const { Pool } = require('pg') const app = express() const pgPool = new Pool(/* 自行填入PostgreSQL连接配置 */) // 配置multer存储到本地磁盘,如需直接拿Buffer存库可替换为multer.memoryStorage() const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, './public/product-images') // 提前创建好对应文件夹 }, filename: (req, file, cb) => { // 重命名避免文件名重复 const fileName = `${Date.now()}-${Math.round(Math.random() * 1e9)}-${file.originalname}` cb(null, fileName) } }) const upload = multer({ storage: storage, limits: { fileSize: 5 * 1024 * 1024 } }) // 限制单文件5M以内 // 接口配置,single('productImage')表示接收单文件,对应前端FormData的文件字段名 app.post('/api/product/create', upload.single('productImage'), async (req, res) => { try { const { name, category, description, price } = req.body const imagePath = `/product-images/${req.file.filename}` // 写入PostgreSQL const result = await pgPool.query( `INSERT INTO products (name, category, description, price, image_url) VALUES ($1, $2, $3, $4, $5) RETURNING id`, [name, category, description, Number(price), imagePath] ) res.json({ code: 0, message: '商品创建成功', productId: result.rows[0].id }) } catch (err) { console.error(err) res.status(500).json({ code: 1, message: '商品创建失败' }) } }) app.listen(3000, () => console.log('服务启动在3000端口'))
PostgreSQL存储说明
如果选择直接存储图片二进制数据,可将对应字段类型设置为BYTEA,配置multer使用内存存储模式后,取req.file.buffer写入数据库即可。
内容的提问来源于stack exchange,提问作者Ashutosh Dubey
相关产品推荐
相关产品推荐

