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

Node.js连接提前终止,CSV导入PostgreSQL仅插入首行问题排查

CSV文件数据插入PostgreSQL时连接提前终止问题

背景

我是Node.js新手,已在Windows Server上搭建Node/Express服务器,对接PostgreSQL数据库。需求是通过HTML表单让用户上传本地CSV文件,并将文件数据插入数据库。

现有代码

app.post('/envoi', upload.single("fichiercsv"), async(req, res) => {
let newClient
try {
    const { identifiant, motdepasse } = req.body
    const clientConfigModifie = {
    ...clientConfigDefaut,
    user: identifiant,
    password: ''
    }
    newClient = new Client(clientConfigModifie)
        
    await newClient.connect()
     
    const rows = []
    const buffer = req.file.buffer
        // console.log(buffer) //ok
    const readableStreamFromBuffer = new stream.Readable()
    readableStreamFromBuffer.push(req.file.buffer)
    readableStreamFromBuffer.push(null)
    await newPromise( (resolve, reject) => {
        fastcsv.parseStream(readableStreamFromBuffer, { headers: false })
            .on('data', us => {
                rows.push(us)   
            })
            .on('end', async() => { 
                rows.shift()
                const usTotal = rows.map( us => us.join("").split(";"))
                // console.log(us)
                for (const us of usTotal) {
                await newClient.query("insert into activite.us (numus, gidgeo) VALUES ($1, $2)", [us[0], us[13]])
                })
                resolve()
            })
            .on("error", error => console.error(error))
        })  
}   
catch(e) {
    console.log("erreur lors du traitement", e)
    res.send(`<h3>échec de la connexion</h3>`)
}
finally {
    try {
        newClient.end()
    }
    catch(e) { 
        console.log(e) 
    }
}
})

问题情况

  • 若省略finally代码块,数据可全部插入数据库,但数据库连接会持续运行;
  • 添加finally代码块后,仅能插入us的第一行数据,且报错:error: Connection terminated at C:\Apache\balbla\

此时newClient.query仅执行一次,连接就莫名终止但未正常关闭,请问我哪里操作有误?

*编辑:已根据@I2yscho的回答更新代码。


问题原因及修正方案

你的代码存在三个关键问题,导致连接提前终止:

  1. Promise拼写错误:代码中newPromise应为new Promise,缺少空格会导致无法正确创建异步等待的Promise,使得后续逻辑没有等待CSV解析完成就进入finally块。
  2. 语法错误导致提前resolve:在end事件的回调中,for循环后面多写了一个}),这会让resolve()在第一个插入操作完成后就被执行,await Promise提前结束,finally块立刻关闭数据库连接,后续插入操作因此失败。
  3. 解析错误未捕获:fastcsv的error事件仅打印错误但未调用reject,导致Promise无法感知解析失败,可能隐藏潜在问题。

修正后的代码

app.post('/envoi', upload.single("fichiercsv"), async(req, res) => {
    let newClient
    try {
        const { identifiant, motdepasse } = req.body
        const clientConfigModifie = {
            ...clientConfigDefaut,
            user: identifiant,
            password: '' // 若需使用用户提交的密码,请改为motdepasse
        }
        newClient = new Client(clientConfigModifie)
            
        await newClient.connect()
        
        const rows = []
        const buffer = req.file.buffer
        const readableStreamFromBuffer = new stream.Readable()
        readableStreamFromBuffer.push(req.file.buffer)
        readableStreamFromBuffer.push(null)
        
        await new Promise( (resolve, reject) => {
            fastcsv.parseStream(readableStreamFromBuffer, { headers: false })
                .on('data', us => {
                    rows.push(us)   
                })
                .on('end', async() => { 
                    rows.shift() // 移除CSV表头行
                    const usTotal = rows.map( us => us.join("").split(";"))
                    // 遍历所有数据行执行插入,确保全部完成后再resolve
                    for (const us of usTotal) {
                        await newClient.query("insert into activite.us (numus, gidgeo) VALUES ($1, $2)", [us[0], us[13]])
                    }
                    resolve()
                })
                .on("error", error => {
                    console.error(error)
                    reject(error) // 解析出错时拒绝Promise,让外层catch捕获
                })
        })  
    }   
    catch(e) {
        console.log("处理过程出错", e)
        res.send(`<h3>连接或处理失败</h3>`)
    }
    finally {
        if (newClient) { // 确保newClient已初始化再尝试关闭
            try {
                await newClient.end() // 等待连接关闭完成
            }
            catch(e) { 
                console.log("关闭连接时出错", e) 
            }
        }
    }
})

额外优化建议

  • 批量插入提升性能:当前循环执行单条插入效率较低,建议使用PostgreSQL批量插入语法(如INSERT INTO ... VALUES (...), (...), ...),减少数据库交互次数。
  • 密码正确传递:代码中password: ''固定为空,若需使用用户提交的密码,应改为password: motdepasse。
  • 流式处理减少内存占用:当前先将所有行存入rows数组再处理,若CSV文件较大会占用大量内存,建议直接在data事件中处理单条数据或批量积累后插入,无需全部存入内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 19:50:23