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

Node.js实现PSQL导出CSV触发用户下载及语法错误修复

需求说明

将psql命令行导出CSV的操作转换为queries.js中的JavaScript函数,实现用户点击前端按钮时,将数据库数据导出为CSV文件并保存到用户本地下载目录。
参考psql命令截图:
psql命令行参考

现存问题

当前编写的函数执行时提示tag_7z8eq73.csv附近存在语法错误,现有代码如下:

后端导出函数

async function exportDatabase(req, res){
return db.any('COPY (SELECT adc_i, adc_v FROM tag_7z8eq73) TO "tag_7z8eq73.csv" DELIMITER "|" CSV HEADER')
    .then(rows => {
        // console.log(rows);
        res.json(rows)
    })
    .catch(error => {
        console.log(error)
    });
}

路由配置

router.get('/export', db.exportDatabase);

前端触发函数

exportData(){
    fetch('http://192.168.1.51:3000/api/v1/export', {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                    },
            })
        .then(res => res.text())
        .then((result) => {
            console.log('database exported')
        })
        .catch((error) => {
            console.log(error)
        });

},
错误原因
  1. SQL语法错误:PostgreSQL中双引号仅用于包裹表名、字段名这类标识符,字符串常量(文件名、分隔符)必须用单引号包裹,原代码用双引号包裹文件名和分隔符,数据库会将其识别为标识符,触发语法错误。
  2. 逻辑错误:COPY TO 文件路径语法是将文件写入PostgreSQL服务所在的服务器磁盘,不会将内容返回给接口响应,就算语法正确,用户也无法下载到本地文件。
  3. 前后端逻辑不匹配:后端返回JSON格式、前端仅打印响应文本,没有处理文件下载流,无法触发浏览器保存文件。
修正方案

1. 后端代码修正

改用COPY TO STDOUT语法直接将CSV内容输出为响应流,设置正确的下载响应头:

const { pipeline } = require('stream/promises');

async function exportDatabase(req, res){
  // 设置CSV下载响应头
  res.setHeader('Content-Type', 'text/csv; charset=utf-8');
  res.setHeader('Content-Disposition', 'attachment; filename="tag_7z8eq73.csv"');

  // 注意SQL中所有字符串值用单引号,输出到STDOUT而非服务器文件
  const exportSql = `COPY (SELECT adc_i, adc_v FROM tag_7z8eq73) TO STDOUT DELIMITER '|' CSV HEADER`;

  try {
    const conn = await db.connect();
    const exportStream = conn.client.query(exportSql);
    // 将数据库导出流直接管道到响应
    await pipeline(exportStream, res);
    conn.done();
  } catch (error) {
    console.error('CSV导出失败:', error);
    res.status(500).send('文件导出失败');
  }
}

注意:如果使用的是pg-promise,确保版本支持流操作,路由绑定导出函数时不要丢失this上下文,可改成router.get('/export', (req, res) => db.exportDatabase(req, res))避免绑定问题。

2. 前端代码修正

处理响应二进制流,手动触发浏览器下载:

exportData(){
  fetch('http://192.168.1.51:3000/api/v1/export', {
    method: 'GET',
  })
  .then(res => {
    if (!res.ok) throw new Error('导出请求失败');
    return res.blob();
  })
  .then(blob => {
    // 创建临时下载链接触发保存
    const tempUrl = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = tempUrl;
    link.download = 'tag_7z8eq73.csv';
    document.body.appendChild(link);
    link.click();
    // 清理临时资源
    window.URL.revokeObjectURL(tempUrl);
    document.body.removeChild(link);
    console.log('数据库导出完成');
  })
  .catch((error) => {
    console.error('导出错误:', error);
  });
},

额外注意事项

  • 提前配置好后端CORS跨域规则,允许前端域名访问导出接口,避免浏览器拦截跨域请求。
  • 数据库连接账号需要有对应表的COPY权限,否则会报权限错误。
  • 如果导出数据量较大,可适当调整接口超时时间,避免导出过程中连接被断开。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:21:18