Node 结合前端实现文件下载(含进度条)

  服务端 fs.stat() 方法获取文件字节流长度通过 fs.createReadStream 获取文件可读流,并返回给前端。前端在 onprogress 中获取文件下载进度,并通过动态创建 a 标签进行文件下载。

服务端代码
const fs = require('fs');
const moment = require('moment');

const getFileTest = function (request, response) {
    // 通过某种方式获取到文件路径
    const filePath = './public/test.xls';
    fs.stat(filePath, function (error, stats) {
        // fs.stat 获取文件字节长度 
        if (error) {
            response.status(400).send({
                status: 400,
                message: '文件大小获取失败,' + error.message,
                time: moment().format('YYYY-MM-DD HH:mm:ss')
            });
        } else {
            let rs = fs.createReadStream(filePath);
            rs.addListener('error', (err) => {
                response.status(400).send({
                    status: 400,
                    message: err.message,
                    time: moment().format('YYYY-MM-DD HH:mm:ss')
                });
            })
            rs.addListener('open', () => {
                response.writeHead(200, {
                    // 文件字节长度,前端下载进度条需要用到
                    'Content-Length': stats.size, 
                    'Content-Type': 'application/octet-stream',
                    // 设置文件名的响应头
                    'File-Name': 'test.xls',
                    // 开放响应头访问权限给前端
                    'Access-Control-Expose-Headers': 'File-Name',
                });
                // 将可读流传给响应对象response
                rs.pipe(response);
            })
        }
    })
}
前端代码

getFile() {
	const xhr = new XMLHttpRequest();
	xhr.timeout = 1000 * 1000;
	xhr.responseType = "blob";
	xhr.open("get", "http://127.0.0.1:8888/download");
	xhr.onprogress = (e) => {
		if (e.total > 0) {
			// 获取进度,用于页面回显
			// 如果 e.total 始终为 0,则可能是服务端未设置 Content-Length 响应头
			this.progress = parseInt((e.loaded / e.total) * 100, 10);
		}
	};
	xhr.onload = (e) => {
		const fileName = xhr.getResponseHeader("File-Name");
        this.downloadFile(xhr.request, fileName);
	};
	xhr.send();
},

downloadFile(fileBlob, fileName) {
	const blob = new Blob([fileBlob], {
		  type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
	});
	if ("download" in document.createElement("a")) {
		const link = document.createElement("a");
		link.download = fileName;
		link.style.display = "none";
		link.href = URL.createObjectURL(blob);
		document.body.appendChild(link);
		link.click();
		URL.revokeObjectURL(link.href);
		document.body.removeChild(link);
	} else {
		navigator.msSaveBlob(blob, fileName);
	}
},
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值