如何在AngularJS前端从AWS S3压缩并下载完整文件夹
嘿,别着急!我完全理解你现在的困扰,毕竟刚接触S3,还要在纯前端实现文件夹打包下载,确实有点绕。我给你一步步拆解,纯浏览器端就能搞定(当然要注意安全前提):
一、先搞定S3的基础配置(核心前提)
因为前端要直接从S3拉取文件,必须先解决跨域访问和文件可读权限两个问题。
1. 设置文件的访问权限(二选一)
方式一:公开可读(适合非敏感文件)
这是纯前端方案最直接的方式,操作步骤:- 打开AWS S3控制台,找到你的存储桶
- 进入目标文件夹,选中所有文件,点击「操作」→「修改权限」
- 在「公有访问」里勾选「读取」,保存即可。
划重点:如果你的文件是敏感数据,千万别用这个方式!会有泄露风险。
方式二:预签名URL(更安全)
这种方式需要后端生成临时的访问URL(因为不能把AWS密钥暴露在前端),但如果完全不想碰后端,就选方式一。
2. 配置S3存储桶的CORS规则
这一步必须做,不然前端会报跨域错误:
- 在S3控制台的存储桶页面,切换到「权限」标签
- 找到「跨域资源共享(CORS)」,点击「编辑」
- 粘贴以下规则(把
https://your-frontend-domain.com换成你实际的前端域名,本地测试可以加http://localhost:3000):
[ { "AllowedHeaders": ["*"], "AllowedMethods": ["GET"], "AllowedOrigins": ["https://your-frontend-domain.com", "http://localhost:3000"], "ExposeHeaders": [] } ]
- 保存配置。
二、前端代码实现(纯浏览器端)
我们会用到三个常用工具库(直接用CDN引入,不用npm):
jszip:用来把文件压缩成ZIP包axios:用来下载S3文件(也可以用原生fetch)FileSaver.js:触发浏览器的下载动作
1. 引入依赖
在你的HTML里加这几行代码:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.0/axios.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
2. 核心功能代码
把下面的代码放到你的JS文件里,记得替换成自己的S3信息:
// 替换成你的S3存储桶名称和目标文件夹前缀 const S3_BUCKET_NAME = '你的存储桶名称'; const FOLDER_PREFIX = '目标文件夹名称/'; // 比如"docs/reports/",注意结尾的斜杠 const S3_BASE_URL = `https://${S3_BUCKET_NAME}.s3.amazonaws.com/`; // 一键下载文件夹的函数 async function downloadFolderAsZip() { try { // 第一步:获取文件夹下的所有文件列表 const listResponse = await axios.get(`https://${S3_BUCKET_NAME}.s3.amazonaws.com/?prefix=${encodeURIComponent(FOLDER_PREFIX)}`); // 解析S3返回的XML格式文件列表 const parser = new DOMParser(); const xmlDoc = parser.parseFromString(listResponse.data, "text/xml"); const keyElements = xmlDoc.getElementsByTagName("Key"); // 过滤掉文件夹本身的占位符,只保留实际文件 const fileKeys = Array.from(keyElements) .map(el => el.textContent) .filter(key => key !== FOLDER_PREFIX); if (fileKeys.length === 0) { alert("文件夹里没有可下载的文件!"); return; } // 第二步:创建ZIP实例 const zip = new JSZip(); // 第三步:批量下载文件并添加到ZIP包 await Promise.all(fileKeys.map(async (key) => { // 去掉文件夹前缀,保留文件原名 const fileName = key.replace(FOLDER_PREFIX, ''); const fileUrl = `${S3_BASE_URL}${encodeURIComponent(key)}`; // 下载文件为Blob格式 const response = await axios.get(fileUrl, { responseType: 'blob' }); // 将文件添加到ZIP包 zip.file(fileName, response.data); })); // 第四步:生成ZIP包并触发下载 const zipContent = await zip.generateAsync({ type: 'blob' }); // 自定义下载的ZIP文件名,比如"reports.zip" saveAs(zipContent, `${FOLDER_PREFIX.replace('/', '')}.zip`); alert("下载完成啦!"); } catch (error) { console.error("下载出错:", error); alert("下载失败,请打开浏览器控制台查看具体错误"); } }
3. 添加触发按钮
在你的HTML里加个按钮,绑定下载函数:
<button onclick="downloadFolderAsZip()">一键下载文件夹所有文件</button>
三、关键注意事项
关于文件列表的安全问题:
上面的代码用了S3的List Objects API来获取文件列表,这需要你的存储桶允许匿名用户执行ListBucket操作。如果不想让别人看到你的文件列表,你可以直接把文件路径硬编码到前端代码里,比如:const fileKeys = [ "docs/reports/file1.pdf", "docs/reports/file2.jpg", "docs/reports/file3.txt" ];这样就不用调用List API了,更安全。
文件大小限制:
如果文件夹里的文件太多或太大,前端压缩可能会导致浏览器卡顿甚至崩溃,这种情况建议用后端处理(比如AWS Lambda + S3),但小文件完全没问题。绝对别暴露AWS密钥:
永远不要在前端代码里写你的AWS Access Key和Secret Key!会被恶意窃取,造成严重安全风险。
内容的提问来源于stack exchange,提问作者Gitesh Sawariya

