如何在Promise中获取Amazon S3存储桶全量文件并处理ContinuationToken分页
S3存储桶全量文件拉取实现方案
现有代码问题
- 分页触发的
s3.listObjectsV2未绑定回调、未等待请求完成就提前resolve,后续分页数据无法收集 allKeys数组每次调用getFiles都会重置为空,无法累积多页拉取结果- 最终返回的是单次请求的文件列表,不是所有分页的合并结果
修正后代码(两种实现可选)
1. async/await 循环版本(逻辑更直观易读)
async function getAllFiles() { let allKeys = []; let continuationToken = null; do { // 构造请求参数,仅存在分页token时携带该参数 const params = { Bucket: bucket, MaxKeys: 5000, ...(continuationToken && { ContinuationToken: continuationToken }) }; // 回调转Promise,等待单页请求完成 const data = await new Promise((resolve, reject) => { s3.listObjectsV2(params, (err, data) => { if (err) return reject(err); resolve(data); }); }); // 合并当前页结果到总列表 allKeys = allKeys.concat(data.Contents); console.log(`已拉取${allKeys.length}个文件`); // 更新分页token,无更多数据时设为null终止循环 continuationToken = data.IsTruncated ? data.NextContinuationToken : null; } while (continuationToken); return allKeys; }
2. Promise递归版本(兼容原代码调用方式)
function getFiles(continuationToken = null, allKeys = []) { const params = { Bucket: bucket, MaxKeys: 5000, ...(continuationToken && { ContinuationToken: continuationToken }) }; return new Promise((resolve, reject) => { s3.listObjectsV2(params, (err, data) => { if (err) return reject(err); const updatedKeys = allKeys.concat(data.Contents); console.log(`已拉取${updatedKeys.length}个文件`); if (data.IsTruncated) { // 存在剩余文件,递归传入下页token和已有结果 resolve(getFiles(data.NextContinuationToken, updatedKeys)); } else { // 全量拉取完成,返回合并后的完整列表 resolve(updatedKeys); } }); }); }
调用方式
和你原有调用逻辑完全兼容,不需要调整后续的filterFiles、mapUrls逻辑:
// 用async版本的调用 getAllFiles() // 用递归版本直接调用原方法名即可 getFiles() .then(filterFiles) .then(mapUrls) .catch(err => console.error('拉取失败:', err));
内容的提问来源于stack exchange,提问作者AppleBaggins
相关产品推荐
相关产品推荐

