TypeScript 实现 Web 服务端返回文件内容
基于已搭建的 TypeScript 开发环境,我们可以快速实现一个 Web 服务端应用,通过 GET 请求接收文件名参数,并返回对应文件的内容。以下是具体实现步骤和代码。
一、添加 HTTP 服务依赖
Node.js 内置了http模块可用于创建 Web 服务,但为了简化开发,我们使用更友好的express框架(需安装类型定义):
bash
mkdir ts-file-server && cd ts-file-server
npm init -y # 生成 package.json
# Express(Web 框架)
npm install express --save
# CORS 中间件(解决跨域问题,可选但推荐)
npm install cors --save
# TypeScript 类型定义(让 TS 识别 Express、Node.js API)
npm install @types/express @types/cors @types/node --save-dev
# TypeScript 编译器
npm install typescript --save-dev
配置 tsconfig.json
在项目根目录创建 tsconfig.json,确保 TS 编译选项正确:
json
{
"compilerOptions": {
"target": "ES2020", // 目标 JS 版本(Node.js 14+ 支持)
"module": "ES2022", // 模块系统(Node.js 用 # ES Module)
"moduleResolution": "node",
"outDir": "./dist", // 编译输出目录(TS → JS 存放于此)
"rootDir": "./src", // 源码根目录(TS 文件存放于此)
"skipLibCheck": true, // 跳过第三方库类型检查(提升速度)
"allowSyntheticDefaultImports": true,
"strict": true // 严格类型检查(推荐开启)
},
"include": ["src/**/*"], // 需要编译的文件(src 目录下所有 TS 文件)
"exclude": ["node_modules"] // 排除 node_modules 目录
}
二、编写 Web 服务代码
在src目录下创建 app.ts 文件,实现接收 GET 请求并返回文件内容的功能:
javascript
import express, { Request, Response } from 'express';
import cors from 'cors';
import fs from 'fs/promises'; // 使用 Promise 风格的 fs 模块(异步非阻塞)
import path from 'path'; // 处理文件路径(跨平台兼容)
// 初始化 Express 应用
const app = express();
const port = 3000; // 服务器端口(可自定义)
// 中间件:解决跨域问题(前端调用时需要)
app.use(cors());
// 中间件:解析 URL 参数(获取 GET 请求中的文件名)
app.use(express.urlencoded({ extended: true }));
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
console.log('当前文件路径:', __filename);
console.log('当前文件所在目录:', __dirname);
const FILES_DIR = path.resolve(__dirname, '../');
console.log('FILES_DIR=', FILES_DIR);
/**
* GET 请求处理:读取文件内容并返回
* 路由:/file?name=文件名(如 /file?name=example.txt)
*/
app.get('/file', async (req: Request, res: Response) => {
try {
// 1. 从请求参数中获取文件名(需校验是否存在)
const fileName = req.query.name?.toString();
console.log(`fileName=${fileName}=`)
if (!fileName) {
return res.status(400).send('请提供文件名(参数名:name)');
}
// 2. 定义文件存储路径(避免目录遍历攻击,限制在 ./files 目录下)
const safePath = path.join(FILES_DIR, 'files', fileName);
console.log(`safePath=${safePath}=`)
// 校验路径是否合法(防止用户传入 ../ 等越界路径)
if (!safePath.startsWith(path.join(FILES_DIR, 'files'))) {
return res.status(403).send('非法文件路径');
}
// 3. 异步读取文件内容(使用 fs.promises.readFile)
const fileContent = await fs.readFile(safePath, 'utf-8');
// 4. 返回文件内容(设置 Content-Type 为文本)
res.set('Content-Type', 'text/plain');
res.send(fileContent);
} catch (err) {
// 处理文件不存在、权限不足等错误
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
res.status(404).send('文件不存在');
} else {
res.status(500).send('服务器内部错误');
}
}
});
// 启动服务器
app.listen(port, () => {
console.log(`文件服务已启动,访问 http://localhost:${port}/file?name=example.txt`);
});
三、准备测试文件
- 在项目根目录创建files文件夹(与src同级):
arduino
mkdir files
-
在files目录下创建测试文件(如example.txt),写入内容:
这是测试文件1的内容
来自TypeScript Web服务
四、编译并运行服务
-
编译 TypeScript 代码:
npx tsc
编译后会在dist/src目录生成server.js。
- 启动 Web 服务:
bash
node dist/src/server.js
终端会输出:
bash
文件服务已启动,访问 http://localhost:3000/file?name=example.txt
五、测试服务
- 打开浏览器或使用 curl 工具访问:
bash
http://localhost:3000/file?name=example.txt
-
成功时会显示example.txt的内容:
这是测试文件1的内容
来自TypeScript Web服务 -
测试错误场景:
-
- 不传递文件名:http://localhost:3000/file → 显示请提供文件名参数
-
- 传递不存在的文件名:http://localhost:3000/file?name=none.txt → 显示文件不存在
六、代码说明
- 安全处理:
-
- 使用join和resolve拼接路径,限制文件只能从files目录读取,防止路径遍历攻击(如?name=../secret.txt)。
-
- 对请求参数进行验证,确保文件名存在。
- HTTP 响应:
-
- 成功时返回 200 状态码和文件内容,设置Content-Type为text/plain确保中文正常显示。
-
- 错误时返回对应状态码(400 参数错误、404 文件不存在)。
- 异步处理:
-
- 使用async/await处理文件读取的异步操作,代码更简洁。
七、扩展方向
- 支持更多文件类型(如图片、JSON),通过文件后缀自动设置Content-Type。
- 添加缓存机制,避免频繁读取相同文件。
- 限制文件大小和访问权限,增强安全性。
通过这个示例,你可以理解如何在 TypeScript 中结合 Node.js 创建 Web 服务,并实现文件读取与 HTTP 响应的完整流程。