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

如何从Node.js Express应用向AJAX/jQuery请求的前端发送数据流

在Node.js Express中向前端(AJAX/jQuery)实时发送数据流的实现方案

刚好之前折腾过类似的需求,结合你给出的SSH执行代码,来一步步拆解怎么实现:

首先,你代码里已经在data事件里调用res.write(data)了,这其实已经是在做流式输出的核心操作,但要让前端能实时接收到数据,还需要前后端配合调整一些细节。

后端Express代码优化

你的SSH执行逻辑已经有了基础,但可以补全一些关键细节,确保流式响应规范且稳定:

  1. 设置响应头:显式声明Transfer-Encoding: chunked(其实Express在你调用res.write而不立即res.end时会自动加,但明确写出来更清晰),同时指定Content-Type避免乱码。
  2. 完善事件处理:在流的close、error事件里记得调用res.end(),不然客户端会一直挂着等待响应结束。

优化后的示例代码:

SSH.prototype.execute = function(shellCommand, options, req, res, callback) {
  function onExec(err, stream) {
    if (err) {
      // 出错时返回错误信息并结束响应
      res.status(500).send(`命令执行失败: ${err.message}`);
      return callback(err);
    }

    const context = { stdout: "", stderr: "" };

    // 告诉客户端这是流式响应,编码为UTF-8
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.setHeader('Transfer-Encoding', 'chunked');

    stream
      .on('close', (code, signal) => {
        context.code = code;
        context.signal = signal;
        // 流关闭后结束响应
        res.end();
        callback(null, context);
      })
      .on('data', (data) => {
        const output = data.toString();
        console.log(output);
        context.stdout += output;
        // 把当前数据块发送给前端
        res.write(output);
        // 如果有自定义回调,顺便触发
        options.onStdout?.(output);
      })
      .on('stderr', (data) => {
        const errOutput = data.toString();
        console.error(errOutput);
        context.stderr += errOutput;
        // 错误输出也可以实时发给前端,加个标识区分
        res.write(`[错误] ${errOutput}`);
        options.onStderr?.(errOutput);
      })
      .on('error', (err) => {
        console.error('数据流异常:', err);
        res.write(`[数据流错误] ${err.message}`);
        res.end();
        callback(err);
      });
  }

  // 这里替换成你实际的SSH命令执行逻辑,比如调用ssh.exec
  // this.ssh.exec(shellCommand, options, onExec);
};

然后在Express路由里直接用这个方法就行:

app.get('/run-ssh-command', (req, res) => {
  const sshInstance = new SSH(); // 初始化你的SSH实例
  // 比如执行一个实时输出的命令,像tail -f日志
  sshInstance.execute('tail -f /var/log/syslog', {}, req, res, (err, result) => {
    if (err) {
      console.error('SSH执行出错:', err);
    } else {
      console.log('命令执行结束,退出码:', result.code);
    }
  });
});

前端AJAX/jQuery处理要点

普通的jQuery $.ajax()默认会等整个响应完成才触发success,所以必须用XHR的onprogress事件来实时捞取数据:

原生XHR实现(推荐)

const logArea = document.getElementById('command-log');
let lastReceivedLength = 0;

const xhr = new XMLHttpRequest();
xhr.open('GET', '/run-ssh-command', true);

// 监听进度事件,实时获取新数据
xhr.onprogress = (e) => {
  const fullResponse = e.currentTarget.responseText;
  // 只取上次之后新增的内容,避免重复渲染
  const newContent = fullResponse.substring(lastReceivedLength);
  if (newContent) {
    logArea.textContent += newContent;
    lastReceivedLength = fullResponse.length;
    // 可以顺便滚动到最新内容
    logArea.scrollTop = logArea.scrollHeight;
  }
};

xhr.onload = () => {
  if (xhr.status >= 200 && xhr.status < 300) {
    console.log('数据流传输完成');
  } else {
    console.error('请求失败:', xhr.statusText);
  }
};

xhr.onerror = () => {
  console.error('网络连接出错');
};

xhr.send();

jQuery兼容方案

jQuery本身没直接支持流式,但可以通过自定义xhr对象来实现:

const $logArea = $('#command-log');
let lastReceivedLength = 0;

$.ajax({
  url: '/run-ssh-command',
  type: 'GET',
  xhr: () => {
    const xhr = new XMLHttpRequest();
    xhr.onprogress = (e) => {
      const fullResponse = e.currentTarget.responseText;
      const newContent = fullResponse.substring(lastReceivedLength);
      if (newContent) {
        $logArea.append(newContent);
        lastReceivedLength = fullResponse.length;
        $logArea.scrollTop($logArea[0].scrollHeight);
      }
    };
    return xhr;
  },
  success: () => {
    console.log('数据流传输结束');
  },
  error: (xhr, status, err) => {
    console.error('请求出错:', err);
  }
});

踩坑提醒

  • 跨域配置:如果前后端跨域,Express的CORS配置要允许自定义头,确保分块传输的头能正常传递。
  • 超时问题:如果是长时间的数据流(比如tail -f),要设置好服务器和客户端的超时时间,比如Express里用req.setTimeout(0)禁用超时(按需调整)。
  • 编码一致性:确保后端输出的编码和响应头里的charset一致,不然前端会出现乱码。

内容的提问来源于stack exchange,提问作者MANOJ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:09:21