一、核心概念先理清
1. express.text() 是什么?
express.text() 是 Express 框架内置的中间件 ,用于解析 HTTP 请求体中 Content-Type 为 text/plain 格式的数据,解析后会将数据挂载到 req.body 上,方便后续路由处理。
- 核心作用:处理纯文本格式的请求体(区别于
express.json()处理 JSON、express.urlencoded()处理表单) - 默认配置:
charset: 'utf-8'、type: 'text/plain',支持自定义扩展
2. fetch() 是什么?
fetch() 是浏览器/Node.js(v18+ 内置)提供的原生 API,用于发送 HTTP 请求,替代传统的 XMLHttpRequest,返回 Promise 对象,支持异步处理请求/响应。
- 发送纯文本请求时,需手动配置
Content-Type: text/plain,并将请求体传入纯文本字符串
二、前置准备
- 初始化项目(后端)
bash
# 创建项目文件夹
mkdir express-fetch-text-demo && cd express-fetch-text-demo
# 初始化 npm
npm init -y
# 安装 express
npm install express
- 环境说明
- 后端:Node.js ≥ 14、Express ≥ 4.16+(
express.text()从 Express 4.16 开始内置) - 前端:现代浏览器(支持
fetch())或 Node.js ≥ 18(内置fetch())
三、完整实战示例
示例1:基础用法(前端浏览器 ↔ Express 后端)
步骤1:搭建 Express 后端(解析纯文本请求)
创建 server.js,配置 express.text() 并编写路由:
javascript
// server.js
const express = require('express');
const app = express();
const port = 3000;
// 配置 express.text() 中间件(全局生效,所有路由均可解析 text/plain 请求体)
// 可自定义配置:比如修改默认编码、扩展支持的 Content-Type
app.text({
charset: 'utf-8', // 编码格式,默认 utf-8
type: 'text/plain' // 匹配的 Content-Type,可写数组如 ['text/plain', 'text/custom']
});
// 解决跨域(前端浏览器请求必备,否则会报 CORS 错误)
app.use((req, res, next) => {
// 允许所有前端域名访问(生产环境需指定具体域名,如 http://localhost:5500)
res.setHeader('Access-Control-Allow-Origin', '*');
// 允许的请求方法
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
// 允许的请求头
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
next();
});
// 1. 接收纯文本请求(POST 方法,推荐用于提交数据)
app.post('/api/receive-text', (req, res) => {
try {
// req.body 即为 express.text() 解析后的纯文本内容
const receivedText = req.body;
console.log('收到纯文本数据:', receivedText);
// 响应给前端(可返回纯文本或 JSON,这里演示返回纯文本)
res.setHeader('Content-Type', 'text/plain');
res.send(`后端已接收你的文本:${receivedText}`);
} catch (error) {
res.status(500).send('服务器解析文本失败:' + error.message);
}
});
// 2. 启动服务器
app.listen(port, () => {
console.log(`后端服务器运行在 http://localhost:${port}`);
});
步骤2:搭建前端页面(用 fetch() 发送纯文本)
创建 index.html,放在任意文件夹(用 VS Code Live Server 启动,默认端口 5500):
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>fetch + express.text() 示例</title>
<style>
.container { margin: 20px; }
textarea { width: 300px; height: 100px; margin-bottom: 10px; }
button { padding: 8px 16px; cursor: pointer; }
#response { margin-top: 10px; color: #333; }
</style>
</head>
<body>
<div class="container">
<h3>输入纯文本发送给后端</h3>
<textarea id="textInput" placeholder="请输入任意纯文本..."></textarea>
<br>
<button id="sendBtn">发送文本</button>
<div id="response"></div>
</div>
<script>
// 1. 获取 DOM 元素
const textInput = document.getElementById('textInput');
const sendBtn = document.getElementById('sendBtn');
const responseDiv = document.getElementById('response');
// 2. 发送纯文本的核心逻辑(fetch 配置)
async function sendTextToServer() {
const textContent = textInput.value.trim();
if (!textContent) {
alert('请输入要发送的文本!');
return;
}
try {
// fetch(url, options)
const response = await fetch('http://localhost:3000/api/receive-text', {
method: 'POST', // 对应后端的 POST 路由
headers: {
// 关键:指定请求体格式为 text/plain(与 express.text() 对应)
'Content-Type': 'text/plain; charset=utf-8'
},
body: textContent // 直接传入纯文本字符串(无需 JSON.stringify)
});
// 处理后端响应(后端返回的是 text/plain,用 response.text() 解析)
const responseText = await response.text();
responseDiv.textContent = '后端响应:' + responseText;
} catch (error) {
responseDiv.textContent = '请求失败:' + error.message;
responseDiv.style.color = 'red';
}
}
// 3. 绑定按钮点击事件
sendBtn.addEventListener('click', sendTextToServer);
</script>
</body>
</html>
步骤3:运行测试
- 启动后端:
node server.js,看到提示后端服务器运行在 http://localhost:3000 - 启动前端:用 VS Code Live Server 打开
index.html,访问http://localhost:5500 - 测试操作:
- 在文本框输入任意内容(如「Hello Express + Fetch!」)
- 点击「发送文本」,前端会显示后端响应
- 后端终端会打印「收到纯文本数据:Hello Express + Fetch!」
示例2:Node.js 端用 fetch() 发送纯文本(无浏览器跨域)
如果你的客户端也是 Node.js 程序(v18+),无需处理 CORS,直接发送请求:
创建 node-client.js:
javascript
// node-client.js
async function sendText() {
const textContent = '这是 Node.js 客户端发送的纯文本';
try {
const response = await fetch('http://localhost:3000/api/receive-text', {
method: 'POST',
headers: {
'Content-Type': 'text/plain'
},
body: textContent
});
const responseText = await response.text();
console.log('后端响应:', responseText);
} catch (error) {
console.error('请求失败:', error);
}
}
// 执行发送
sendText();
运行测试:
- 确保后端
server.js已启动 - 执行客户端:
node node-client.js - 终端会输出后端响应,同时后端终端打印接收的文本
四、高级配置与注意事项
1. express.text() 高级配置
javascript
// 自定义配置示例
app.text({
charset: 'gbk', // 适配中文老式编码(需确保前端发送时编码一致)
type: ['text/plain', 'text/custom', 'application/x-text'], // 扩展支持的 Content-Type
limit: '10kb' // 限制请求体大小,默认 100kb,超出会报错
});
2. fetch() 发送纯文本的关键配置
| 配置项 | 必选/可选 | 说明 |
|---|---|---|
method |
必选 | 需与后端路由一致(推荐 POST/PUT/DELETE,GET 无请求体,无需解析) |
headers.Content-Type |
必选 | 必须设为 text/plain(或 express.text() 配置的扩展类型),否则后端无法解析 |
body |
必选 | 直接传入纯文本字符串(无需序列化,与 JSON.stringify 区分) |
credentials |
可选 | 若需要携带 Cookie(如登录状态),设为 include(浏览器端跨域时需后端配合) |
3. 响应处理的对应方式
后端返回不同格式,前端需用对应的解析方法:
后端响应 Content-Type |
前端解析方法 |
|---|---|
text/plain |
response.text() |
application/json |
response.json() |
blob(文件) |
response.blob() |
示例:后端返回 JSON,前端解析
javascript
// 后端路由
app.post('/api/receive-text-json', (req, res) => {
res.json({
code: 200,
msg: '接收成功',
data: req.body
});
});
// 前端 fetch 解析
const response = await fetch('http://localhost:3000/api/receive-text-json', { /* 配置同上 */ });
const responseData = await response.json(); // 用 json() 解析
console.log(responseData.data); // 拿到纯文本内容
4. 常见问题排查
问题1:req.body 为 undefined
- 原因1:未配置
express.text()中间件(或配置在路由之后,中间件未生效) - 原因2:前端
Content-Type配置错误(如写成application/json) - 原因3:请求方法为
GET(GET 无请求体,req.body始终为undefined) - 解决方案:确保
app.text()在路由之前配置,前端Content-Type与后端匹配,使用POST/PUT方法
问题2:跨域报错(Access-Control-Allow-Origin)
- 原因:浏览器同源策略限制,前端域名与后端不一致
- 解决方案:
- 后端添加 CORS 中间件(如示例1中的自定义 CORS,或使用
cors包) - 生产环境避免
*,指定具体前端域名:res.setHeader('Access-Control-Allow-Origin', 'http://xxx.com') - 可选:使用代理(如 Vite 代理、Nginx 反向代理)
- 后端添加 CORS 中间件(如示例1中的自定义 CORS,或使用
问题3:中文乱码
- 原因:前后端编码不一致(如后端
charset: 'gbk',前端用utf-8) - 解决方案:
- 统一使用
utf-8编码(推荐) - 前端发送时指定编码:
'Content-Type': 'text/plain; charset=gbk' - 后端解析时对应配置
charset: 'gbk'
- 统一使用
问题4:请求体过大报错
- 原因:
express.text()默认限制 100kb,超出会返回 413 错误 - 解决方案:自定义
limit配置,如app.text({ limit: '1mb' })
五、生产环境最佳实践
-
避免全局
app.text():若只有部分路由需要解析纯文本,可将中间件配置在单个路由上:javascript// 仅该路由生效 app.post('/api/only-text', express.text(), (req, res) => { // 处理逻辑 }); -
使用
cors包替代自定义 CORS :生产环境更稳定:bashnpm install corsjavascriptconst cors = require('cors'); // 全局启用 app.use(cors({ origin: 'http://your-frontend.com', // 指定前端域名 credentials: true // 允许携带 Cookie })); -
添加请求验证 :解析后验证
req.body是否合法,避免空数据:javascriptapp.post('/api/receive-text', (req, res) => { if (!req.body || req.body.length === 0) { return res.status(400).send('请传入有效的纯文本数据'); } // 后续逻辑 }); -
错误捕获 :使用
try/catch包裹解析逻辑,或全局错误处理中间件:javascript// 全局错误处理 app.use((err, req, res, next) => { console.error('服务器错误:', err.stack); res.status(500).send('服务器内部错误'); });
总结
express.text()专用于解析text/plain格式请求体,解析后数据挂载在req.body,需配置在路由之前。fetch()发送纯文本时,必须指定headers: { 'Content-Type': 'text/plain' },且body直接传入字符串。- 浏览器端需处理 CORS 跨域,前后端编码需统一,避免中文乱码和
req.body为undefined的问题。 - 生产环境建议按需使用
express.text()、用cors包处理跨域,并添加请求验证和错误捕获。