Node做excel导入学习到的finish与end事件监听

重点: finsih事件来自 stream.Writable 类,end 事件来自 stream.Readable 类。

 

背景

因为一个excel导入数据的需求,我用node通过使用formidable,fs,xlsx,mysql四个模块对上传的excel文件进行了解析,并将excel中的文件的内容导入到数据库中。

业务逻辑很简单,使用formidable模块接收前端上传的excel文件,使用fs模块将虚拟路径的临时文件转换为本地文件,再通过xlsx.parse()进行解析excel文件进行导入操作。

一切都是这样的理所应当,写完后一次测试立马成功。

带着小小的成就感,想连续多点几下,发现了个问题,xlsx.parse()偶尔会将excel文件中的内容解析为空。这是为什么呢?研究下代码。

 

代码

解析放在readStream的end事件监听回调中

           // ...省略接收前端文件的代码部分
           // temPath在前面代码部分已定义并赋值

            let readStream=fs.createReadStream(tempPath); 

			// 生成新的文件名
			let fileName = new Date().valueOf(),
				fileExt = FileUtil.getUploadFileExt(tempPath); // 获取文件后缀名

            // 若文件类型不符合要求返回
			if(fileExt==undefined||fileExt==""||(fileExt!="xls"&&fileExt!="xlsx")){
				fs.unlinkSync(tempPath);// 同步删除虚拟文件
				ctx.body = "文件类型有误";
				return resolve("抛出异常");
			}

			// 无论是什么格式的EXCEL都转换成xlsx格式进行保存
			curPath = DirPath+fileName+".xlsx";

            
			let writeStream=fs.createWriteStream(curPath); // 创建可写流

			readStream.pipe(writeStream); // 将可读流数据传入可写流

			// 文件写入完成监听
			readStream.on('end',async function(){
				fs.unlinkSync(tempPath);// 同步删除虚拟文件
                await insertList(curPath); // 数据插入操作
				fs.unlinkSync(curPath);// 同步删除本地文件
				ctx.body = "导入成功";
				resolve("完成");
			});




// 插入数据
const  insertList = async path=>{

    let table = xlsx.parse(path);
    //  ....省略插入数据代码部分
}

当代码这样写的时候,会出现我在故事背景中的问题,会有某几次xlsx解析curPath对应的这个文件下的excel文件为空。

我从代码的执行顺序,是否在解析时候本地文件已经被删除等多个角度进行排查问题,进行了代码排查,结果都没找到原因。我就想是不是readStream触发end事件的时候writeStream中的数据还没有写完呢?或者说解析的时候还没有写好呢?于是我就去查询了下node文档中的stream模块里去查找writeable是否也有end事件,结果发现了文章开头部分的重点:finsih事件来自 stream.Writable 类,end 事件来自 stream.Readable 类。

将readStream.on("end")替换为writeStream.on("finish")后,这个问题就解决了。以后明白了,解析可读流文件还是要在writeStream的finish事件中进行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值