如何使用AWS JavaScript/Node SDK批量下载S3文件夹内所有文件
解决S3文件夹批量下载到本地的问题
S3本身没有真正的“文件夹”概念,所谓的文件夹其实是对象Key的前缀。你之前的问题在于用getObject直接请求前缀(文件夹路径),但这个接口只能获取单个具体文件;另外写入根目录/downloadedFiles可能没有权限,且必须指定具体文件路径。
要实现批量下载整个文件夹到运行时创建的本地目录,步骤如下:
实现步骤
- 先用
listObjectsV2列出目标前缀下的所有文件对象 - 过滤掉代表“文件夹”的空对象(Key以
/结尾的条目) - 为每个文件构建本地存储路径,递归创建所需的目录
- 逐个下载每个文件到对应的本地路径
完整代码示例
import { S3 } from 'aws-sdk'; import fs from 'fs'; import path from 'path'; // 初始化S3客户端 const s3 = new S3(); // 配置参数 const config = { bucketName: 'my-bucket', s3FolderPrefix: 'my-folder/', // 要下载的S3前缀(文件夹路径) localRootDir: './downloadedFiles' // 本地目标根目录 }; // 批量下载S3前缀下的所有文件 async function downloadS3Folder() { try { // 列出S3前缀下的所有对象 const listParams = { Bucket: config.bucketName, Prefix: config.s3FolderPrefix }; const response = await s3.listObjectsV2(listParams).promise(); if (!response.Contents || response.Contents.length === 0) { console.log('目标前缀下没有文件'); return; } // 遍历每个对象 for (const obj of response.Contents) { // 跳过代表文件夹的空对象(Key以/结尾) if (obj.Key.endsWith('/')) continue; // 构建本地文件路径:去掉S3前缀,拼接本地根目录 const relativePath = obj.Key.replace(config.s3FolderPrefix, ''); const localFilePath = path.join(config.localRootDir, relativePath); const localDir = path.dirname(localFilePath); // 递归创建本地目录(如果不存在) if (!fs.existsSync(localDir)) { fs.mkdirSync(localDir, { recursive: true }); } // 下载S3文件到本地 const getParams = { Bucket: config.bucketName, Key: obj.Key }; const fileStream = fs.createWriteStream(localFilePath); await new Promise((resolve, reject) => { s3.getObject(getParams) .createReadStream() .pipe(fileStream) .on('finish', resolve) .on('error', reject); }); console.log(`已下载文件: ${localFilePath}`); } console.log('所有文件下载完成'); } catch (err) { console.error('下载过程中出错:', err); } } // 执行下载 downloadS3Folder();
关键点说明
listObjectsV2:用来获取指定前缀下的所有对象,替代getObject无法处理前缀的问题- 递归创建目录:用
fs.mkdirSync的recursive: true参数,自动创建多级目录 - 路径处理:用
path模块拼接本地路径,避免跨系统路径分隔符问题 - 异步流处理:将
getObject的流操作包装成Promise,确保每个文件下载完成后再处理下一个
内容的提问来源于stack exchange,提问作者Sabo Boz
相关产品推荐
相关产品推荐

