You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:27:35