Nodo combinado con front-end para realizar la descarga de archivos (incluida la barra de progreso)

  El fs.stat()método del servidor obtiene la longitud del flujo de bytes del archivo al fs.createReadStreamobtener el flujo legible del archivo y lo devuelve al front-end. El front-end onprogressobtiene el progreso de la descarga del archivo en y descarga el archivo mediante la creación dinámica de una etiqueta.

código del servidor

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);
            })
        }
    })
}

código de front-end


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);
	}
},

Supongo que te gusta

Origin blog.csdn.net/dark_cy/article/details/124771364
Recomendado
Clasificación