Node.js中for循环遍历WebDAV createReadStream下载空文件问题
问题根因
- 循环使用
var声明变量存在变量提升问题,异步执行时fileName会被覆盖为最后一次循环的值,导致大部分读流请求的路径错误。 getDirectoryContents返回结果同时包含文件和子目录,未做类型判断直接对目录创建读流,会返回空内容。- 同时发起大量并发读流请求,超过SFCC WebDAV默认的并发连接限制,服务器会主动拒绝多数请求,返回空数据。
- 未监听流的完成/错误事件,无法感知请求执行状态,可能出现连接提前释放、传输未完成的情况。
修正后的代码
let fs = require('fs'); let { createClient } = require("webdav"); // 将流下载封装为Promise,方便异步控制 function downloadFile(client, remoteFileName, localPath) { return new Promise((resolve, reject) => { const readStream = client.createReadStream(remoteFileName); const writeStream = fs.createWriteStream(localPath + remoteFileName); readStream.pipe(writeStream); // 监听完成和错误事件 writeStream.on('finish', () => resolve(`下载完成:${remoteFileName}`)); readStream.on('error', (err) => reject(`下载失败${remoteFileName}:${err.message}`)); writeStream.on('error', (err) => reject(`写入失败${remoteFileName}:${err.message}`)); }); } let client = createClient( "https://../demandware.servlet/webdav/Sites/Logs", { username: "*", password: "*" } ); client .getDirectoryContents("/") .then(async function(contents) { const localBasePath = "C:/Users/../Documents/COE/../logs/"; // 顺序下载,控制并发避免触发服务器限制 for (let item of contents) { // 只处理文件类型,跳过子目录 if (item.type === 'file') { try { const res = await downloadFile(client, item.filename, localBasePath); console.log(res); } catch (err) { console.error(err); } } } });
核心修改点
- 把
var替换为let,结合for...of循环利用块级作用域,保证每次循环的文件参数正确。 - 增加文件类型判断,跳过子目录避免无效请求。
- 封装Promise控制下载流程,采用顺序下载的方式避免触发SFCC WebDAV的并发限制。
- 增加流事件监听,可感知每个文件的下载状态,避免传输未完成就释放资源。
内容的提问来源于stack exchange,提问作者sonal
相关产品推荐
相关产品推荐

