Node.js获取SQL Server数据后实现txt文件下载的异步取值问题
问题原因
你的代码核心问题是数据库连接、查询操作都是异步执行的:sql.connect、sqlRequest.query都是非阻塞API,传入的回调函数会等数据库操作完成后才执行,但你把设置响应头、返回响应的逻辑写在了回调外面,代码不会等数据库查询返回结果就直接执行了res.end(text),这时候查询结果还没拿到,自然无法把数据库值赋给响应内容。
另外你的代码还存在几个隐患:
- 未声明
text变量,会造成隐式全局变量污染 - 用字符串拼接SQL语句,存在SQL注入风险
- 数据库操作报错时仅打印控制台日志,未给客户端返回响应,会导致请求挂起超时
- 未判断查询结果是否为空,查无对应ID时会抛出读取属性的异常
修复后的完整代码
把响应逻辑全部移到数据库查询的回调内部,等拿到查询结果后再组装内容返回,同时补上错误处理、参数化查询:
const http = require('http'); const url = require('url'); const sql = require('mssql'); // 数据库配置 const config = { user: 'test_user', password: '123', server: 'localhost', database: 'TestDatabase', port: 1433, trustServerCertificate: true, }; http.createServer(function (req, res) { // 解析URL获取ID参数,做基础类型校验 const queryObject = url.parse(req.url, true).query.ID; if (!queryObject || isNaN(Number(queryObject))) { res.writeHead(400, {'Content-Type': 'text/plain; charset=utf-8'}); return res.end('无效的ID参数'); } // 连接数据库 sql.connect(config, function (err) { if (err) { res.writeHead(500, {'Content-Type': 'text/plain; charset=utf-8'}); return res.end('数据库连接失败:' + err.message); } const sqlRequest = new sql.Request(); // 用参数化查询代替字符串拼接,避免SQL注入 sqlRequest.input('ID', sql.Int, Number(queryObject)); const sqlQuery = 'SELECT Testvalue FROM TestDatabase.dbo.TestTable WHERE ID = @ID'; sqlRequest.query(sqlQuery, function (err, data) { if (err) { sql.close(); res.writeHead(500, {'Content-Type': 'text/plain; charset=utf-8'}); return res.end('数据查询失败:' + err.message); } // 判断是否查询到对应数据 if (!data.recordset || data.recordset.length === 0) { sql.close(); res.writeHead(404, {'Content-Type': 'text/plain; charset=utf-8'}); return res.end('未找到对应ID的数据'); } // 组装txt文件内容 const text = "This is a content of a txt file. Value from database = " + data.recordset[0].Testvalue; // 关闭数据库连接,设置下载响应头返回内容 sql.close(); res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8', 'Content-Disposition': 'attachment; filename=file.txt' }); res.end(text); }); }); }).listen(8080, '127.0.0.1'); console.log('Server running at http://127.0.0.1:8080/');
关键改动说明
- 所有响应返回逻辑全部放在异步回调内部,确保拿到数据库结果后再输出响应
- 新增参数校验、错误分支的响应处理,避免请求挂起
- 改用参数化查询传入ID参数,彻底避免SQL注入风险
- 增加查询结果为空的判断,避免空值读取报错
- 修正响应头的
Content-Type为标准的text/plain,加上charset设置避免中文乱码 - 显式声明
text为局部变量,避免全局污染
内容的提问来源于stack exchange,提问作者tutu
相关产品推荐
相关产品推荐

